Files
azuredatastudio/src/vs/workbench/browser/viewlet.ts
Anthony Dresser 4ba6a979ba Merge from vscode a4177f50c475fc0fa278a78235e3bee9ffdec781 (#8649)
* Merge from vscode a4177f50c475fc0fa278a78235e3bee9ffdec781

* distro

* fix tests
2019-12-11 22:42:23 -08:00

205 lines
7.4 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import * as DOM from 'vs/base/browser/dom';
import { Registry } from 'vs/platform/registry/common/platform';
import { Action, IAction } from 'vs/base/common/actions';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IViewlet } from 'vs/workbench/common/viewlet';
import { CompositeDescriptor, CompositeRegistry } from 'vs/workbench/browser/composite';
import { IConstructorSignature0, IInstantiationService, BrandedService } from 'vs/platform/instantiation/common/instantiation';
import { ToggleSidebarVisibilityAction, ToggleSidebarPositionAction } from 'vs/workbench/browser/actions/layoutActions';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { URI } from 'vs/base/common/uri';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree';
import { AbstractTree } from 'vs/base/browser/ui/tree/abstractTree';
import { assertIsDefined } from 'vs/base/common/types';
import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { PaneComposite } from 'vs/workbench/browser/panecomposite';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
export abstract class Viewlet extends PaneComposite implements IViewlet {
constructor(id: string,
viewPaneContainer: ViewPaneContainer,
@ITelemetryService telemetryService: ITelemetryService,
@IStorageService protected storageService: IStorageService,
@IInstantiationService protected instantiationService: IInstantiationService,
@IThemeService themeService: IThemeService,
@IContextMenuService protected contextMenuService: IContextMenuService,
@IExtensionService protected extensionService: IExtensionService,
@IWorkspaceContextService protected contextService: IWorkspaceContextService,
@IWorkbenchLayoutService protected layoutService: IWorkbenchLayoutService,
@IConfigurationService protected configurationService: IConfigurationService
) {
super(id, viewPaneContainer, telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService);
}
getContextMenuActions(): IAction[] {
const parentActions = [...super.getContextMenuActions()];
if (parentActions.length) {
parentActions.push(new Separator());
}
const toggleSidebarPositionAction = new ToggleSidebarPositionAction(ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.getLabel(this.layoutService), this.layoutService, this.configurationService);
return [...parentActions, toggleSidebarPositionAction,
<IAction>{
id: ToggleSidebarVisibilityAction.ID,
label: nls.localize('compositePart.hideSideBarLabel', "Hide Side Bar"),
enabled: true,
run: () => this.layoutService.setSideBarHidden(true)
}];
}
}
/**
* A viewlet descriptor is a leightweight descriptor of a viewlet in the workbench.
*/
export class ViewletDescriptor extends CompositeDescriptor<Viewlet> {
public static create<Services extends BrandedService[]>(
ctor: { new(...services: Services): Viewlet },
id: string,
name: string,
cssClass?: string,
order?: number,
iconUrl?: URI
): ViewletDescriptor {
return new ViewletDescriptor(ctor as IConstructorSignature0<Viewlet>, id, name, cssClass, order, iconUrl);
}
private constructor(
ctor: IConstructorSignature0<Viewlet>,
id: string,
name: string,
cssClass?: string,
order?: number,
readonly iconUrl?: URI
) {
super(ctor, id, name, cssClass, order, id);
}
}
export const Extensions = {
Viewlets: 'workbench.contributions.viewlets'
};
export class ViewletRegistry extends CompositeRegistry<Viewlet> {
private defaultViewletId: string | undefined;
/**
* Registers a viewlet to the platform.
*/
registerViewlet(descriptor: ViewletDescriptor): void {
super.registerComposite(descriptor);
}
/**
* Deregisters a viewlet to the platform.
*/
deregisterViewlet(id: string): void {
if (id === this.defaultViewletId) {
throw new Error('Cannot deregister default viewlet');
}
super.deregisterComposite(id);
}
/**
* Returns the viewlet descriptor for the given id or null if none.
*/
getViewlet(id: string): ViewletDescriptor {
return this.getComposite(id) as ViewletDescriptor;
}
/**
* Returns an array of registered viewlets known to the platform.
*/
getViewlets(): ViewletDescriptor[] {
return this.getComposites() as ViewletDescriptor[];
}
/**
* Sets the id of the viewlet that should open on startup by default.
*/
setDefaultViewletId(id: string): void {
this.defaultViewletId = id;
}
/**
* Gets the id of the viewlet that should open on startup by default.
*/
getDefaultViewletId(): string {
return assertIsDefined(this.defaultViewletId);
}
}
Registry.add(Extensions.Viewlets, new ViewletRegistry());
/**
* A reusable action to show a viewlet with a specific id.
*/
export class ShowViewletAction extends Action {
constructor(
id: string,
name: string,
private readonly viewletId: string,
@IViewletService protected viewletService: IViewletService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService
) {
super(id, name);
this.enabled = !!this.viewletService && !!this.editorGroupService;
}
run(): Promise<any> {
// Pass focus to viewlet if not open or focused
if (this.otherViewletShowing() || !this.sidebarHasFocus()) {
return this.viewletService.openViewlet(this.viewletId, true);
}
// Otherwise pass focus to editor group
this.editorGroupService.activeGroup.focus();
return Promise.resolve(true);
}
private otherViewletShowing(): boolean {
const activeViewlet = this.viewletService.getActiveViewlet();
return !activeViewlet || activeViewlet.getId() !== this.viewletId;
}
private sidebarHasFocus(): boolean {
const activeViewlet = this.viewletService.getActiveViewlet();
const activeElement = document.activeElement;
const sidebarPart = this.layoutService.getContainer(Parts.SIDEBAR_PART);
return !!(activeViewlet && activeElement && sidebarPart && DOM.isAncestor(activeElement, sidebarPart));
}
}
export class CollapseAction extends Action {
constructor(tree: AsyncDataTree<any, any, any> | AbstractTree<any, any, any>, enabled: boolean, clazz?: string) {
super('workbench.action.collapse', nls.localize('collapse', "Collapse All"), clazz, enabled, () => {
tree.collapseAll();
return Promise.resolve(undefined);
});
}
}