Skip to content

Commit

Permalink
Fix #49145
Browse files Browse the repository at this point in the history
- Enable/Disable viewlets by views when context
- Move viewlet enablement/disablement to views service
- Fix - adopt if a viewlet extension is disabled/removed
  • Loading branch information
sandy081 committed May 28, 2018
1 parent 7eff96c commit f60d780
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 66 deletions.
9 changes: 4 additions & 5 deletions src/vs/workbench/api/browser/viewsContainersExtensionPoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,11 @@ class ViewsContainersExtensionHandler implements IWorkbenchContribution {
}

private registerTestViewContainer(): void {
const id = 'test';
const title = localize('test', "Test");
const cssClass = `extensionViewlet-${id}`;
const cssClass = `extensionViewlet-test`;
const icon = require.toUrl('./media/test.svg');

this.registerCustomViewlet({ id, title, icon }, TEST_VIEW_CONTAINER_ORDER, cssClass);
this.registerCustomViewlet({ id: ViewLocation.TEST.id, title, icon }, TEST_VIEW_CONTAINER_ORDER, cssClass);
}

private handleAndRegisterCustomViewContainers() {
Expand Down Expand Up @@ -139,13 +138,13 @@ class ViewsContainersExtensionHandler implements IWorkbenchContribution {
const cssClass = `extensionViewlet-${descriptor.id}`;
// TODO@extensionLocation
const icon = join(extension.extensionLocation.fsPath, descriptor.icon);
this.registerCustomViewlet({ id: descriptor.id, title: descriptor.title, icon }, TEST_VIEW_CONTAINER_ORDER + index + 1, cssClass);
this.registerCustomViewlet({ id: `workbench.view.extension.${descriptor.id}`, title: descriptor.title, icon }, TEST_VIEW_CONTAINER_ORDER + index + 1, cssClass);
});
}

private registerCustomViewlet(descriptor: IUserFriendlyViewsContainerDescriptor, order: number, cssClass: string): void {
const viewletRegistry = Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets);
const id = `workbench.view.extension.${descriptor.id}`;
const id = descriptor.id;

if (!viewletRegistry.getViewlet(id)) {

Expand Down
51 changes: 15 additions & 36 deletions src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND,
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { CompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBar';
import { ToggleCompositePinnedAction, ICompositeBar } from 'vs/workbench/browser/parts/compositebar/compositeBarActions';
import { ViewLocation, ViewsRegistry } from 'vs/workbench/common/views';
import { ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { Dimension, createCSSRule } from 'vs/base/browser/dom';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
Expand Down Expand Up @@ -57,7 +56,6 @@ export class ActivitybarPart extends Part {
private globalActivityIdToActions: { [globalActivityId: string]: GlobalActivityAction; };

private placeholderComposites: IPlaceholderComposite[] = [];
private extensionsRegistrationCompleted: boolean = false;
private compositeBar: CompositeBar;
private compositeActions: { [compositeId: string]: { activityAction: ViewletActivityAction, pinnedAction: ToggleCompositePinnedAction } };

Expand Down Expand Up @@ -101,16 +99,13 @@ export class ActivitybarPart extends Part {
}

private onDidRegisterExtensions(): void {
this.extensionsRegistrationCompleted = true;
this.removeNotExistingPlaceholderComposites();
this.updateCompositebar();
}

private registerListeners(): void {

this.toUnbind.push(this.viewletService.onDidViewletRegister(() => this.updateCompositebar()));
this.toUnbind.push(ViewsRegistry.onViewsRegistered(() => this.updateCompositebar()));
this.toUnbind.push(ViewsRegistry.onViewsDeregistered(() => this.updateCompositebar()));

// Activate viewlet action on opening of a viewlet
this.toUnbind.push(this.viewletService.onDidViewletOpen(viewlet => this.compositeBar.activateComposite(viewlet.getId())));
Expand All @@ -119,7 +114,7 @@ export class ActivitybarPart extends Part {
this.toUnbind.push(this.viewletService.onDidViewletClose(viewlet => this.compositeBar.deactivateComposite(viewlet.getId())));
this.toUnbind.push(this.viewletService.onDidViewletEnablementChange(({ id, enabled }) => {
if (enabled) {
this.compositeBar.addComposite(this.viewletService.getViewlet(id), true);
this.compositeBar.addComposite(this.viewletService.getViewlet(id));
} else {
this.removeComposite(id);
}
Expand Down Expand Up @@ -226,26 +221,18 @@ export class ActivitybarPart extends Part {
private updateCompositebar(): void {
const viewlets = this.viewletService.getViewlets();
for (const viewlet of viewlets) {
const hasPlaceholder = this.placeholderComposites.some(c => c.id === viewlet.id);

// Add the composite if it has views registered or
// If it was existing before and the extensions registration is not yet completed.
if (this.hasRegisteredViews(viewlet)
|| (hasPlaceholder && !this.extensionsRegistrationCompleted)
) {
this.compositeBar.addComposite(viewlet, false);
// Pin it by default if it is new => it does not has a placeholder
if (!hasPlaceholder) {
this.compositeBar.pin(viewlet.id);
}
this.enableCompositeActions(viewlet);
const activeViewlet = this.viewletService.getActiveViewlet();
if (activeViewlet && activeViewlet.getId() === viewlet.id) {
this.compositeBar.pin(viewlet.id);
this.compositeBar.activateComposite(viewlet.id);
}
} else {
this.removeComposite(viewlet.id);
this.compositeBar.addComposite(viewlet);

// Pin it by default if it is new => it does not has a placeholder
if (this.placeholderComposites.every(c => c.id !== viewlet.id)) {
this.compositeBar.pin(viewlet.id);
}

this.enableCompositeActions(viewlet);
const activeViewlet = this.viewletService.getActiveViewlet();
if (activeViewlet && activeViewlet.getId() === viewlet.id) {
this.compositeBar.pin(viewlet.id);
this.compositeBar.activateComposite(viewlet.id);
}
}
}
Expand All @@ -254,7 +241,7 @@ export class ActivitybarPart extends Part {
const viewlets = this.viewletService.getViewlets();
for (const { id } of this.placeholderComposites) {
if (viewlets.every(viewlet => viewlet.id !== id)) {
this.compositeBar.addComposite({ id, name: id, order: void 0 }, false);
this.compositeBar.addComposite({ id, name: id, order: void 0 });
}
}
}
Expand Down Expand Up @@ -288,14 +275,6 @@ export class ActivitybarPart extends Part {
}
}

private hasRegisteredViews(viewlet: ViewletDescriptor): boolean {
const viewLocation = ViewLocation.get(viewlet.id);
if (viewLocation) {
return ViewsRegistry.getViews(viewLocation).length > 0;
}
return true;
}

public getPinned(): string[] {
return this.viewletService.getViewlets().map(v => v.id).filter(id => this.compositeBar.isPinned(id));
}
Expand Down Expand Up @@ -324,7 +303,7 @@ export class ActivitybarPart extends Part {
}

public shutdown(): void {
const state = this.viewletService.getViewlets().filter(viewlet => this.hasRegisteredViews(viewlet)).map(viewlet => ({ id: viewlet.id, iconUrl: viewlet.iconUrl }));
const state = this.viewletService.getViewlets().filter(viewlet => this.compositeBar.isPinned(viewlet.id)).map(viewlet => ({ id: viewlet.id, iconUrl: viewlet.iconUrl }));
this.storageService.store(ActivitybarPart.PLACEHOLDER_VIEWLETS, JSON.stringify(state), StorageScope.GLOBAL);
super.shutdown();
}
Expand Down
6 changes: 3 additions & 3 deletions src/vs/workbench/browser/parts/compositebar/compositeBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
this.updateCompositeSwitcher();
}

public addComposite({ id, name, order }: { id: string; name: string, order: number }, open: boolean): void {
public addComposite({ id, name, order }: { id: string; name: string, order: number }): void {
const state = this.storedState.filter(s => s.id === id)[0];
const pinned = state ? state.pinned : true;
let index = order >= 0 ? order : this.model.items.length;
Expand All @@ -139,8 +139,8 @@ export class CompositeBar extends Widget implements ICompositeBar {
// Add to the model
if (this.model.add(id, name, order, index)) {
this.computeSizes([this.model.findItem(id)]);
if (pinned || open) {
this.pin(id, open);
if (pinned) {
this.pin(id);
} else {
this.updateCompositeSwitcher();
}
Expand Down
6 changes: 3 additions & 3 deletions src/vs/workbench/browser/parts/panel/panelPart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
});
this.toUnbind.push(this.compositeBar);
for (const panel of this.getPanels()) {
this.compositeBar.addComposite(panel, false);
this.compositeBar.addComposite(panel);
}
this.activePanelContextKey = ActivePanelContext.bindTo(contextKeyService);
this.onDidPanelOpen(this._onDidPanelOpen, this, this.disposables);
Expand All @@ -116,7 +116,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {

private registerListeners(): void {

this.toUnbind.push(this.registry.onDidRegister(panelDescriptor => this.compositeBar.addComposite(panelDescriptor, false)));
this.toUnbind.push(this.registry.onDidRegister(panelDescriptor => this.compositeBar.addComposite(panelDescriptor)));

// Activate panel action on opening of a panel
this.toUnbind.push(this.onDidPanelOpen(panel => {
Expand Down Expand Up @@ -198,7 +198,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
if (descriptor && descriptor.enabled !== enabled) {
descriptor.enabled = enabled;
if (enabled) {
this.compositeBar.addComposite(descriptor, true);
this.compositeBar.addComposite(descriptor);
} else {
this.removeComposite(id);
}
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/browser/parts/views/contributableViews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export interface IViewItem {
active: boolean;
}

class ViewDescriptorCollection {
export class ViewDescriptorCollection {

private contextKeys = new CounterSet<string>();
private items: IViewItem[] = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,30 @@ import { FileIconThemableWorkbenchTree } from 'vs/workbench/browser/parts/views/
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { Emitter, Event } from 'vs/base/common/event';
import { ViewDescriptorCollection } from './contributableViews';
import { Registry } from 'vs/platform/registry/common/platform';
import { ViewletRegistry, Extensions as ViewletExtensions } from 'vs/workbench/browser/viewlet';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';

export class CustomViewsService extends Disposable implements IViewsService {
export class ViewsService extends Disposable implements IViewsService {

_serviceBrand: any;

private viewers: Map<string, CustomTreeViewer> = new Map<string, CustomTreeViewer>();

constructor(
@IInstantiationService private instantiationService: IInstantiationService,
@IViewletService private viewletService: IViewletService
@ILifecycleService private lifecycleService: ILifecycleService,
@IViewletService private viewletService: IViewletService,
@IStorageService private storageService: IStorageService
) {
super();

ViewLocation.all.forEach(viewLocation => this.onDidRegisterViewLocation(viewLocation));
this._register(ViewLocation.onDidRegister(viewLocation => this.onDidRegisterViewLocation(viewLocation)));
this._register(Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).onDidRegister(viewlet => this.viewletService.setViewletEnablement(viewlet.id, this.storageService.getBoolean(`viewservice.${viewlet.id}.enablement`, StorageScope.GLOBAL, viewlet.id !== ViewLocation.TEST.id))));

this.createViewers(ViewsRegistry.getAllViews());
this._register(ViewsRegistry.onViewsRegistered(viewDescriptors => this.createViewers(viewDescriptors)));
this._register(ViewsRegistry.onViewsDeregistered(viewDescriptors => this.removeViewers(viewDescriptors)));
Expand Down Expand Up @@ -72,6 +84,18 @@ export class CustomViewsService extends Disposable implements IViewsService {
return TPromise.as(null);
}

private onDidRegisterViewLocation(viewLocation: ViewLocation): void {
const viewDescriptorCollection = this._register(this.instantiationService.createInstance(ViewDescriptorCollection, viewLocation));
this._register(viewDescriptorCollection.onDidChange(() => this.updateViewletEnablement(viewLocation, viewDescriptorCollection)));
this.lifecycleService.when(LifecyclePhase.Eventually).then(() => this.updateViewletEnablement(viewLocation, viewDescriptorCollection));
}

private updateViewletEnablement(viewLocation: ViewLocation, viewDescriptorCollection: ViewDescriptorCollection): void {
const enabled = viewDescriptorCollection.viewDescriptors.length > 0;
this.viewletService.setViewletEnablement(viewLocation.id, enabled);
this.storageService.store(`viewservice.${viewLocation.id}.enablement`, enabled, StorageScope.GLOBAL);
}

private createViewers(viewDescriptors: IViewDescriptor[]): void {
for (const viewDescriptor of viewDescriptors) {
if ((<ICustomViewDescriptor>viewDescriptor).treeView) {
Expand Down
17 changes: 14 additions & 3 deletions src/vs/workbench/common/views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,34 @@ import { IViewlet } from 'vs/workbench/common/viewlet';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IDisposable } from 'vs/base/common/lifecycle';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { values } from 'vs/base/common/map';

export class ViewLocation {

private static readonly _onDidRegister: Emitter<ViewLocation> = new Emitter<ViewLocation>();
static readonly onDidRegister: Event<ViewLocation> = ViewLocation._onDidRegister.event;

private static locations: Map<string, ViewLocation> = new Map<string, ViewLocation>();
static register(id: string): ViewLocation {
const viewLocation = new ViewLocation(id);
ViewLocation.locations.set(id, viewLocation);
return viewLocation;
if (!ViewLocation.locations.has(id)) {
const viewLocation = new ViewLocation(id);
ViewLocation.locations.set(id, viewLocation);
ViewLocation._onDidRegister.fire(viewLocation);
}
return ViewLocation.get(id);
}
static get(value: string): ViewLocation {
return ViewLocation.locations.get(value);
}
static get all(): ViewLocation[] {
return values(ViewLocation.locations);
}

static readonly Explorer: ViewLocation = ViewLocation.register('workbench.view.explorer');
static readonly Debug: ViewLocation = ViewLocation.register('workbench.view.debug');
static readonly Extensions: ViewLocation = ViewLocation.register('workbench.view.extensions');
static readonly SCM: ViewLocation = ViewLocation.register('workbench.view.scm.views.contributed');
static readonly TEST: ViewLocation = ViewLocation.register('workbench.view.extension.test');

private constructor(private _id: string) { }
get id(): string { return this._id; }
Expand Down
15 changes: 9 additions & 6 deletions src/vs/workbench/electron-browser/workbench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ import { IListService, ListService } from 'vs/platform/list/browser/listService'
import { domEvent } from 'vs/base/browser/event';
import { InputFocusedContext } from 'vs/platform/workbench/common/contextkeys';
import { IViewsService } from 'vs/workbench/common/views';
import { CustomViewsService } from 'vs/workbench/browser/parts/views/customView';
import { ViewsService } from 'vs/workbench/browser/parts/views/views';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { NotificationService } from 'vs/workbench/services/notification/common/notificationService';
import { NotificationsCenter } from 'vs/workbench/browser/parts/notifications/notificationsCenter';
Expand Down Expand Up @@ -387,9 +387,11 @@ export class Workbench implements IPartService {
}

perf.mark('willRestoreViewlet');
restorePromises.push(this.viewletService.openViewlet(viewletIdToRestore).then(() => {
perf.mark('didRestoreViewlet');
}));
restorePromises.push(this.viewletService.openViewlet(viewletIdToRestore)
.then(viewlet => viewlet || this.viewletService.openViewlet(this.viewletService.getDefaultViewletId()))
.then(() => {
perf.mark('didRestoreViewlet');
}));
}

// Restore Panel
Expand Down Expand Up @@ -575,7 +577,7 @@ export class Workbench implements IPartService {
serviceCollection.set(IPanelService, this.panelPart);

// Custom views service
const customViewsService = this.instantiationService.createInstance(CustomViewsService);
const customViewsService = this.instantiationService.createInstance(ViewsService);
serviceCollection.set(IViewsService, customViewsService);

// Activity service (activitybar part)
Expand Down Expand Up @@ -872,7 +874,8 @@ export class Workbench implements IPartService {
else if (!hidden && !this.sidebarPart.getActiveViewlet()) {
const viewletToOpen = this.sidebarPart.getLastActiveViewletId();
if (viewletToOpen) {
promise = this.sidebarPart.openViewlet(viewletToOpen, true);
promise = this.viewletService.openViewlet(viewletToOpen, true)
.then(viewlet => viewlet || this.viewletService.openViewlet(this.viewletService.getDefaultViewletId(), true));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,29 @@ export class SearchViewLocationUpdater implements IWorkbenchContribution {
@IPanelService panelService: IPanelService,
@IConfigurationService configurationService: IConfigurationService
) {
const updateSearchViewLocation = () => {
const updateSearchViewLocation = (open: boolean) => {
const config = configurationService.getValue<ISearchConfiguration>();
if (config.search.location === 'panel') {
viewletService.setViewletEnablement(VIEW_ID, false);
panelService.setPanelEnablement(VIEW_ID, true);
if (open) {
panelService.openPanel(VIEW_ID);
}
} else {
panelService.setPanelEnablement(VIEW_ID, false);
viewletService.setViewletEnablement(VIEW_ID, true);
if (open) {
viewletService.openViewlet(VIEW_ID);
}
}
};

configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('search.location')) {
updateSearchViewLocation();
updateSearchViewLocation(true);
}
});

updateSearchViewLocation();
updateSearchViewLocation(false);
}
}
Loading

0 comments on commit f60d780

Please sign in to comment.