mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-27 17:23:21 -05:00
201 lines
5.7 KiB
TypeScript
201 lines
5.7 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 { Registry } from 'vs/platform/registry/common/platform';
|
|
import { IAction } from 'vs/base/common/actions';
|
|
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
|
import { ITree, IActionProvider } from 'vs/base/parts/tree/browser/tree';
|
|
import { IInstantiationService, IConstructorSignature0, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
|
|
|
/**
|
|
* The action bar contributor allows to add actions to an actionbar in a given context.
|
|
*/
|
|
export class ActionBarContributor {
|
|
|
|
/**
|
|
* Returns true if this contributor has actions for the given context.
|
|
*/
|
|
hasActions(context: unknown): boolean {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of primary actions in the given context.
|
|
*/
|
|
getActions(context: unknown): ReadonlyArray<IAction> {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Some predefined scopes to contribute actions to
|
|
*/
|
|
export const Scope = {
|
|
|
|
/**
|
|
* Actions inside tree widgets.
|
|
*/
|
|
VIEWER: 'viewer'
|
|
};
|
|
|
|
/**
|
|
* The ContributableActionProvider leverages the actionbar contribution model to find actions.
|
|
*/
|
|
export class ContributableActionProvider implements IActionProvider {
|
|
private readonly registry: IActionBarRegistry = Registry.as<IActionBarRegistry>(Extensions.Actionbar);
|
|
|
|
private toContext(tree: ITree, element: unknown): unknown {
|
|
return {
|
|
viewer: tree,
|
|
element: element
|
|
};
|
|
}
|
|
|
|
hasActions(tree: ITree, element: unknown): boolean {
|
|
const context = this.toContext(tree, element);
|
|
|
|
const contributors = this.registry.getActionBarContributors(Scope.VIEWER);
|
|
for (const contributor of contributors) {
|
|
if (contributor.hasActions(context)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
getActions(tree: ITree, element: unknown): ReadonlyArray<IAction> {
|
|
const actions: IAction[] = [];
|
|
const context = this.toContext(tree, element);
|
|
|
|
// Collect Actions
|
|
const contributors = this.registry.getActionBarContributors(Scope.VIEWER);
|
|
for (const contributor of contributors) {
|
|
if (contributor.hasActions(context)) {
|
|
actions.push(...contributor.getActions(context));
|
|
}
|
|
}
|
|
|
|
return prepareActions(actions);
|
|
}
|
|
}
|
|
|
|
// Helper function used in parts to massage actions before showing in action areas
|
|
export function prepareActions(actions: IAction[]): IAction[] {
|
|
if (!actions.length) {
|
|
return actions;
|
|
}
|
|
|
|
// Clean up leading separators
|
|
let firstIndexOfAction = -1;
|
|
for (let i = 0; i < actions.length; i++) {
|
|
if (actions[i].id === Separator.ID) {
|
|
continue;
|
|
}
|
|
|
|
firstIndexOfAction = i;
|
|
break;
|
|
}
|
|
|
|
if (firstIndexOfAction === -1) {
|
|
return [];
|
|
}
|
|
|
|
actions = actions.slice(firstIndexOfAction);
|
|
|
|
// Clean up trailing separators
|
|
for (let h = actions.length - 1; h >= 0; h--) {
|
|
const isSeparator = actions[h].id === Separator.ID;
|
|
if (isSeparator) {
|
|
actions.splice(h, 1);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Clean up separator duplicates
|
|
let foundAction = false;
|
|
for (let k = actions.length - 1; k >= 0; k--) {
|
|
const isSeparator = actions[k].id === Separator.ID;
|
|
if (isSeparator && !foundAction) {
|
|
actions.splice(k, 1);
|
|
} else if (!isSeparator) {
|
|
foundAction = true;
|
|
} else if (isSeparator) {
|
|
foundAction = false;
|
|
}
|
|
}
|
|
|
|
return actions;
|
|
}
|
|
|
|
export const Extensions = {
|
|
Actionbar: 'workbench.contributions.actionbar'
|
|
};
|
|
|
|
export interface IActionBarRegistry {
|
|
/**
|
|
* Registers an Actionbar contributor. It will be called to contribute actions to all the action bars
|
|
* that are used in the Workbench in the given scope.
|
|
*/
|
|
registerActionBarContributor(scope: string, ctor: IConstructorSignature0<ActionBarContributor>): void;
|
|
|
|
/**
|
|
* Returns an array of registered action bar contributors known to the workbench for the given scope.
|
|
*/
|
|
getActionBarContributors(scope: string): ActionBarContributor[];
|
|
|
|
/**
|
|
* Starts the registry by providing the required services.
|
|
*/
|
|
start(accessor: ServicesAccessor): void;
|
|
}
|
|
|
|
class ActionBarRegistry implements IActionBarRegistry {
|
|
private readonly actionBarContributorConstructors: { scope: string; ctor: IConstructorSignature0<ActionBarContributor>; }[] = [];
|
|
private readonly actionBarContributorInstances: Map<string, ActionBarContributor[]> = new Map();
|
|
private instantiationService!: IInstantiationService;
|
|
|
|
start(accessor: ServicesAccessor): void {
|
|
this.instantiationService = accessor.get(IInstantiationService);
|
|
|
|
while (this.actionBarContributorConstructors.length > 0) {
|
|
const entry = this.actionBarContributorConstructors.shift()!;
|
|
this.createActionBarContributor(entry.scope, entry.ctor);
|
|
}
|
|
}
|
|
|
|
private createActionBarContributor(scope: string, ctor: IConstructorSignature0<ActionBarContributor>): void {
|
|
const instance = this.instantiationService.createInstance(ctor);
|
|
let target = this.actionBarContributorInstances.get(scope);
|
|
if (!target) {
|
|
target = [];
|
|
this.actionBarContributorInstances.set(scope, target);
|
|
}
|
|
target.push(instance);
|
|
}
|
|
|
|
private getContributors(scope: string): ActionBarContributor[] {
|
|
return this.actionBarContributorInstances.get(scope) || [];
|
|
}
|
|
|
|
registerActionBarContributor(scope: string, ctor: IConstructorSignature0<ActionBarContributor>): void {
|
|
if (!this.instantiationService) {
|
|
this.actionBarContributorConstructors.push({
|
|
scope: scope,
|
|
ctor: ctor
|
|
});
|
|
} else {
|
|
this.createActionBarContributor(scope, ctor);
|
|
}
|
|
}
|
|
|
|
getActionBarContributors(scope: string): ActionBarContributor[] {
|
|
return this.getContributors(scope).slice(0);
|
|
}
|
|
}
|
|
|
|
Registry.add(Extensions.Actionbar, new ActionBarRegistry());
|