未验证 提交 929753d4 编写于 作者: S SteVen Batten 提交者: GitHub

use uuid and try dynamic titles (#94686)

* use uuid for generated containers
* use dynamic titles based on container views
* add icons to built-in views
上级 92ff20ac
......@@ -6,7 +6,7 @@
import 'vs/css!./media/activitybarpart';
import * as nls from 'vs/nls';
import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { GLOBAL_ACTIVITY_ID } from 'vs/workbench/common/activity';
import { GLOBAL_ACTIVITY_ID, IActivity } from 'vs/workbench/common/activity';
import { Registry } from 'vs/platform/registry/common/platform';
import { Part } from 'vs/workbench/browser/part';
import { GlobalActivityActionViewItem, ViewletActivityAction, ToggleViewletAction, PlaceHolderToggleCompositePinnedAction, PlaceHolderViewletActivityAction, AccountsActionViewItem } from 'vs/workbench/browser/parts/activitybar/activitybarActions';
......@@ -29,7 +29,7 @@ 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 { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IViewlet } from 'vs/workbench/common/viewlet';
import { isUndefinedOrNull, assertIsDefined } from 'vs/base/common/types';
import { isUndefinedOrNull, assertIsDefined, isString } from 'vs/base/common/types';
import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { Schemas } from 'vs/base/common/network';
......@@ -458,12 +458,10 @@ export class ActivitybarPart extends Part implements IActivityBarService {
for (const viewlet of viewlets) {
this.enableCompositeActions(viewlet);
const viewContainer = this.getViewContainer(viewlet.id);
if (viewContainer?.hideIfEmpty) {
const viewDescriptors = this.viewDescriptorService.getViewDescriptors(viewContainer);
this.onDidChangeActiveViews(viewlet, viewDescriptors);
this.viewletDisposables.set(viewlet.id, viewDescriptors.onDidChangeActiveViews(() => this.onDidChangeActiveViews(viewlet, viewDescriptors)));
}
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)));
}
}
......@@ -477,10 +475,33 @@ export class ActivitybarPart extends Part implements IActivityBarService {
this.hideComposite(viewletId);
}
private onDidChangeActiveViews(viewlet: ViewletDescriptor, viewDescriptors: IViewDescriptorCollection): void {
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);
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),
keybindingId: viewlet.keybindingId
};
const { activityAction, pinnedAction } = this.getCompositeActions(viewlet.id);
activityAction.setActivity(activity);
if (pinnedAction instanceof PlaceHolderToggleCompositePinnedAction) {
pinnedAction.setActivity(activity);
}
}
private onDidChangeActiveViews(viewlet: ViewletDescriptor, viewDescriptors: IViewDescriptorCollection, hideIfEmpty?: boolean): void {
if (viewDescriptors.activeViewDescriptors.length) {
this.updateActivity(viewlet, viewDescriptors);
this.compositeBar.addComposite(viewlet);
} else {
} else if (hideIfEmpty) {
this.hideComposite(viewlet.id);
}
}
......
......@@ -39,6 +39,7 @@ import { ViewMenuActions } from 'vs/workbench/browser/parts/views/viewMenuAction
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;
......@@ -238,9 +239,27 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
}
}
private updateActivity(panel: PanelDescriptor, viewDescriptors: IViewDescriptorCollection): void {
const viewDescriptor = viewDescriptors.activeViewDescriptors[0];
const activity: IActivity = {
id: panel.id,
name: viewDescriptor.name,
keybindingId: panel.keybindingId
};
const { activityAction, pinnedAction } = this.getCompositeActions(panel.id);
activityAction.setActivity(activity);
if (pinnedAction instanceof PlaceHolderToggleCompositePinnedAction) {
pinnedAction.setActivity(activity);
}
}
private onDidChangeActiveViews(panel: PanelDescriptor, viewDescriptors: IViewDescriptorCollection): void {
if (viewDescriptors.activeViewDescriptors.length) {
this.compositeBar.addComposite(panel);
this.updateActivity(panel, viewDescriptors);
} else {
this.hideComposite(panel.id);
}
......
......@@ -906,15 +906,19 @@ 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 = allViewDescriptors.some(v => this.viewDescriptorService.getDefaultContainer(v.id) === this.viewContainer) ? this.viewContainer.name : allViewDescriptors[0].name;
if (this.isViewMergedWithContainer()) {
const paneItemTitle = this.paneItems[0].pane.title;
if (this.options.donotShowContainerTitleWhenMergedWithContainer || this.viewContainer.name === paneItemTitle) {
if (this.options.donotShowContainerTitleWhenMergedWithContainer || containerTitle === paneItemTitle) {
return this.paneItems[0].pane.title;
}
return paneItemTitle ? `${this.viewContainer.name}: ${paneItemTitle}` : this.viewContainer.name;
return paneItemTitle ? `${containerTitle}: ${paneItemTitle}` : containerTitle;
}
return this.viewContainer.name;
return containerTitle;
}
private showContextMenu(event: StandardMouseEvent): void {
......
......@@ -110,12 +110,12 @@ Registry.as<IViewsRegistry>(ViewExtensions.ViewsRegistry).registerViews([{
// Register default debug views
const viewsRegistry = Registry.as<IViewsRegistry>(ViewExtensions.ViewsRegistry);
viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), ctorDescriptor: new SyncDescriptor(VariablesView), order: 10, weight: 40, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer);
viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), ctorDescriptor: new SyncDescriptor(WatchExpressionsView), order: 20, weight: 10, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer);
viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), ctorDescriptor: new SyncDescriptor(CallStackView), order: 30, weight: 30, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer);
viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), ctorDescriptor: new SyncDescriptor(BreakpointsView), order: 40, weight: 20, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: ContextKeyExpr.or(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer);
viewsRegistry.registerViews([{ id: WelcomeView.ID, name: WelcomeView.LABEL, ctorDescriptor: new SyncDescriptor(WelcomeView), order: 10, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer);
viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), ctorDescriptor: new SyncDescriptor(LoadedScriptsView), order: 35, weight: 5, canToggleVisibility: true, canMoveView: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer);
viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), containerIcon: 'codicon-debug-alt-2', ctorDescriptor: new SyncDescriptor(VariablesView), order: 10, weight: 40, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer);
viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), containerIcon: 'codicon-debug-alt-2', ctorDescriptor: new SyncDescriptor(WatchExpressionsView), order: 20, weight: 10, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer);
viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), containerIcon: 'codicon-debug-alt-2', ctorDescriptor: new SyncDescriptor(CallStackView), order: 30, weight: 30, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer);
viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), containerIcon: 'codicon-debug-alt-2', ctorDescriptor: new SyncDescriptor(BreakpointsView), order: 40, weight: 20, canToggleVisibility: true, canMoveView: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: ContextKeyExpr.or(CONTEXT_BREAKPOINTS_EXIST, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer);
viewsRegistry.registerViews([{ id: WelcomeView.ID, name: WelcomeView.LABEL, containerIcon: 'codicon-debug-alt-2', ctorDescriptor: new SyncDescriptor(WelcomeView), order: 10, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer);
viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), containerIcon: 'codicon-debug-alt-2', ctorDescriptor: new SyncDescriptor(LoadedScriptsView), order: 35, weight: 5, canToggleVisibility: true, canMoveView: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer);
registerCommands();
......
......@@ -123,6 +123,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor
return {
id: EmptyView.ID,
name: EmptyView.NAME,
containerIcon: 'codicon-files',
ctorDescriptor: new SyncDescriptor(EmptyView),
order: 1,
canToggleVisibility: true,
......@@ -136,6 +137,7 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor
return {
id: ExplorerView.ID,
name: localize('folders', "Folders"),
containerIcon: 'codicons-files',
ctorDescriptor: new SyncDescriptor(ExplorerView),
order: 1,
canToggleVisibility: false,
......
......@@ -333,6 +333,7 @@ export class MainPaneDescriptor implements IViewDescriptor {
readonly id = MainPane.ID;
readonly name = MainPane.TITLE;
readonly containerIcon = 'codicon-source-control';
readonly ctorDescriptor: SyncDescriptor<MainPane>;
readonly canToggleVisibility = true;
readonly hideByDefault = false;
......
......@@ -69,6 +69,7 @@ export class EmptyPane extends ViewPane {
export class EmptyPaneDescriptor implements IViewDescriptor {
readonly id = EmptyPane.ID;
readonly name = EmptyPane.TITLE;
readonly containerIcon = 'codicon-source-control';
readonly ctorDescriptor = new SyncDescriptor(EmptyPane);
readonly canToggleVisibility = true;
readonly hideByDefault = false;
......
......@@ -16,6 +16,8 @@ import { Event, Emitter } from 'vs/base/common/event';
import { firstIndex } from 'vs/base/common/arrays';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { generateUuid } from 'vs/base/common/uuid';
import { localize } from 'vs/nls';
class CounterSet<T> implements IReadableSet<T> {
......@@ -173,7 +175,6 @@ class ViewDescriptorCollection extends Disposable implements IViewDescriptorColl
interface ICachedViewContainerInfo {
containerId: string;
location?: ViewContainerLocation;
sourceViewId?: string;
}
export class ViewDescriptorService extends Disposable implements IViewDescriptorService {
......@@ -198,7 +199,6 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
private readonly viewContainersRegistry: IViewContainersRegistry;
private cachedViewInfo: Map<string, ICachedViewContainerInfo>;
private generatedContainerSourceViewIds: Map<string, string>;
private _cachedViewPositionsValue: string | undefined;
private get cachedViewPositionsValue(): string {
......@@ -233,7 +233,6 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
this.viewContainersRegistry = Registry.as<IViewContainersRegistry>(ViewExtensions.ViewContainersRegistry);
this.viewsRegistry = Registry.as<IViewsRegistry>(ViewExtensions.ViewsRegistry);
this.generatedContainerSourceViewIds = new Map<string, string>();
this.cachedViewInfo = this.getCachedViewPositions();
......@@ -271,9 +270,8 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
if (containerData.cachedContainerInfo && this.shouldGenerateContainer(containerData.cachedContainerInfo)) {
const containerInfo = containerData.cachedContainerInfo;
const sourceViewDescriptor = this.viewsRegistry.getView(containerInfo.sourceViewId!);
if (sourceViewDescriptor && !this.viewContainersRegistry.get(containerId)) {
this.registerViewContainerForSingleView(sourceViewDescriptor, containerInfo.location!);
if (!this.viewContainersRegistry.get(containerId)) {
this.registerGeneratedViewContainer(containerInfo.location!, containerId);
}
}
......@@ -309,12 +307,8 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
// check if we should generate this container
if (this.shouldGenerateContainer(containerInfo)) {
const sourceView = this.getViewDescriptor(containerInfo.sourceViewId!);
if (sourceView) {
this.registerViewContainerForSingleView(sourceView, containerInfo.location!);
continue;
}
this.registerGeneratedViewContainer(containerInfo.location!, containerId);
continue;
}
if (fallbackToDefault) {
......@@ -354,7 +348,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
}
private shouldGenerateContainer(containerInfo: ICachedViewContainerInfo): boolean {
return !!containerInfo.sourceViewId && containerInfo.location !== undefined;
return containerInfo.containerId.startsWith(ViewDescriptorService.COMMON_CONTAINER_ID_PREFIX) && containerInfo.location !== undefined;
}
private onDidDeregisterViews(views: IViewDescriptor[], viewContainer: ViewContainer): void {
......@@ -422,7 +416,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
}
moveViewToLocation(view: IViewDescriptor, location: ViewContainerLocation): void {
let container = this.registerViewContainerForSingleView(view, location);
let container = this.registerGeneratedViewContainer(location);
this.moveViewsToContainer([view], container);
}
......@@ -494,14 +488,14 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
}
}
private registerViewContainerForSingleView(sourceView: IViewDescriptor, location: ViewContainerLocation): ViewContainer {
const id = this.generateContainerIdFromSourceViewId(sourceView.id, location);
private registerGeneratedViewContainer(location: ViewContainerLocation, existingId?: string): ViewContainer {
const id = existingId || this.generateContainerId(location);
return this.viewContainersRegistry.registerViewContainer({
id,
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [id, `${id}.state`, { mergeViewWithContainerWhenSingleView: true }]),
name: sourceView.name,
icon: location === ViewContainerLocation.Sidebar ? sourceView.containerIcon || 'codicon-window' : undefined,
ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [id, `${id}.state`, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]),
name: localize('generatedContainerName', "Custom Views"),
icon: location === ViewContainerLocation.Sidebar ? 'codicon-window' : undefined,
hideIfEmpty: true
}, location);
}
......@@ -535,12 +529,8 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
const prevViewContainer = this.getViewContainer(viewId);
const newViewContainerInfo = newCachedPositions.get(viewId)!;
// Verify if we need to create the destination container
if (newViewContainerInfo.sourceViewId) {
const sourceViewDescriptor = this.getViewDescriptor(newViewContainerInfo.sourceViewId);
if (!this.viewContainersRegistry.get(newViewContainerInfo.containerId) && sourceViewDescriptor) {
this.registerViewContainerForSingleView(sourceViewDescriptor, newViewContainerInfo.location!);
}
if (!this.viewContainersRegistry.get(newViewContainerInfo.containerId)) {
this.registerGeneratedViewContainer(newViewContainerInfo.location!, newViewContainerInfo.containerId);
}
// Try moving to the new container
......@@ -574,11 +564,11 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
}
// Generated Container Id Format
// {Common Prefix}.{Location}.{Uniqueness Id}
// Old Format (deprecated)
// {Common Prefix}.{Uniqueness Id}.{Source View Id}
private generateContainerIdFromSourceViewId(viewId: string, location: ViewContainerLocation): string {
const result = `${ViewDescriptorService.COMMON_CONTAINER_ID_PREFIX}.${location === ViewContainerLocation.Panel ? 'panel' : 'sidebar'}.${viewId}`;
this.generatedContainerSourceViewIds.set(result, viewId);
return result;
private generateContainerId(location: ViewContainerLocation): string {
return `${ViewDescriptorService.COMMON_CONTAINER_ID_PREFIX}.${location === ViewContainerLocation.Panel ? 'panel' : 'sidebar'}.${generateUuid()}`;
}
private getStoredCachedViewPositionsValue(): string {
......@@ -593,12 +583,10 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
this.viewContainersRegistry.all.forEach(viewContainer => {
const viewDescriptorCollection = this.getViewDescriptors(viewContainer);
viewDescriptorCollection.allViewDescriptors.forEach(viewDescriptor => {
const sourceViewId = this.generatedContainerSourceViewIds.get(viewContainer.id);
const containerLocation = this.getViewContainerLocation(viewContainer);
this.cachedViewInfo.set(viewDescriptor.id, {
containerId: viewContainer.id,
location: containerLocation,
sourceViewId: sourceViewId
location: containerLocation
});
});
});
......@@ -682,9 +670,8 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
private addViews(container: ViewContainer, views: IViewDescriptor[]): void {
// Update in memory cache
const location = this.getViewContainerLocation(container);
const sourceViewId = this.generatedContainerSourceViewIds.get(container.id);
views.forEach(view => {
this.cachedViewInfo.set(view.id, { containerId: container.id, location, sourceViewId });
this.cachedViewInfo.set(view.id, { containerId: container.id, location });
this.getOrCreateDefaultViewLocationContextKey(view).set(this.getDefaultContainer(view.id) === container);
});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册