Use menu registry for global activity actions

This commit is contained in:
Sandeep Somavarapu 2019-06-11 19:13:43 +02:00
parent 29dadcc476
commit 6150587c12
14 changed files with 136 additions and 116 deletions

View file

@ -98,7 +98,8 @@ export const enum MenuId {
CommentThreadTitle,
CommentThreadActions,
CommentTitle,
CommentActions
CommentActions,
GlobalActivity
}
export interface IMenuActionOptions {

View file

@ -8,11 +8,11 @@ import * as nls from 'vs/nls';
import * as DOM from 'vs/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch';
import { Action } from 'vs/base/common/actions';
import { Action, IAction } from 'vs/base/common/actions';
import { KeyCode } from 'vs/base/common/keyCodes';
import { dispose } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { SyncActionDescriptor, IMenuService, MenuId } from 'vs/platform/actions/common/actions';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { Registry } from 'vs/platform/registry/common/platform';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@ -21,11 +21,14 @@ import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant }
import { ActivityAction, ActivityActionViewItem, ICompositeBar, ICompositeBarColors, ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositeBarActions';
import { ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions';
import { IActivity, IGlobalActivity } from 'vs/workbench/common/activity';
import { IActivity, IGlobalActivityRegistry, GlobalActivityActionsExtensions } from 'vs/workbench/common/activity';
import { ACTIVITY_BAR_FOREGROUND } from 'vs/workbench/common/theme';
import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService';
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { fillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
export class ViewletActivityAction extends ActivityAction {
@ -104,20 +107,15 @@ export class ToggleViewletAction extends Action {
}
}
export class GlobalActivityAction extends ActivityAction {
constructor(activity: IGlobalActivity) {
super(activity);
}
}
export class GlobalActivityActionViewItem extends ActivityActionViewItem {
constructor(
action: GlobalActivityAction,
action: ActivityAction,
colors: (theme: ITheme) => ICompositeBarColors,
@IThemeService themeService: IThemeService,
@IContextMenuService protected contextMenuService: IContextMenuService
@IMenuService private readonly menuService: IMenuService,
@IContextMenuService protected contextMenuService: IContextMenuService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
) {
super(action, { draggable: false, colors, icon: true }, themeService);
}
@ -148,16 +146,26 @@ export class GlobalActivityActionViewItem extends ActivityActionViewItem {
}
private showContextMenu(): void {
const globalAction = this._action as GlobalActivityAction;
const activity = globalAction.activity as IGlobalActivity;
const actions = activity.getActions();
const globalActivityActions: IAction[] = [];
const globalActivityMenu = this.menuService.createMenu(MenuId.GlobalActivity, this.contextKeyService);
fillInActionBarActions(globalActivityMenu, undefined, { primary: [], secondary: globalActivityActions });
for (const activity of Registry.as<IGlobalActivityRegistry>(GlobalActivityActionsExtensions).getActivities()) {
const actions = activity.getActions();
if (actions.length) {
globalActivityActions.push(new Separator(), ...actions);
}
}
const containerPosition = DOM.getDomNodePagePosition(this.container);
const location = { x: containerPosition.left + containerPosition.width / 2, y: containerPosition.top };
this.contextMenuService.showContextMenu({
getAnchor: () => location,
getActions: () => actions,
onHide: () => dispose(actions)
getActions: () => globalActivityActions,
onHide: () => {
globalActivityMenu.dispose();
dispose(globalActivityActions);
}
});
}
}

View file

@ -7,10 +7,10 @@ import 'vs/css!./media/activitybarpart';
import * as nls from 'vs/nls';
import { illegalArgument } from 'vs/base/common/errors';
import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { GlobalActivityExtensions, IGlobalActivityRegistry } from 'vs/workbench/common/activity';
import { GLOBAL_ACTIVITY_ID } from 'vs/workbench/common/activity';
import { Registry } from 'vs/platform/registry/common/platform';
import { Part } from 'vs/workbench/browser/part';
import { GlobalActivityActionViewItem, GlobalActivityAction, ViewletActivityAction, ToggleViewletAction, PlaceHolderToggleCompositePinnedAction, PlaceHolderViewletActivityAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions';
import { GlobalActivityActionViewItem, ViewletActivityAction, ToggleViewletAction, PlaceHolderToggleCompositePinnedAction, PlaceHolderViewletActivityAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IBadge } from 'vs/workbench/services/activity/common/activity';
import { IWorkbenchLayoutService, Parts, Position as SideBarPosition } from 'vs/workbench/services/layout/browser/layoutService';
@ -25,7 +25,7 @@ import { Dimension, addClass } from 'vs/base/browser/dom';
import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { URI, UriComponents } from 'vs/base/common/uri';
import { ToggleCompositePinnedAction, ICompositeBarColors } from 'vs/workbench/browser/parts/compositeBarActions';
import { ToggleCompositePinnedAction, ICompositeBarColors, ActivityAction } from 'vs/workbench/browser/parts/compositeBarActions';
import { ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { IViewsService, IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainer, TEST_VIEW_CONTAINER_ID, IViewDescriptorCollection } from 'vs/workbench/common/views';
import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
@ -60,8 +60,8 @@ export class ActivitybarPart extends Part implements IActivityBarService {
//#endregion
private globalActionBar: ActionBar;
private globalActivityIdToActions: Map<string, GlobalActivityAction> = new Map();
private globalActivityAction: ActivityAction;
private globalActivityActionBar: ActionBar;
private cachedViewlets: ICachedViewlet[] = [];
@ -163,22 +163,16 @@ export class ActivitybarPart extends Part implements IActivityBarService {
return this.compositeBar.showActivity(viewletOrActionId, badge, clazz, priority);
}
return this.showGlobalActivity(viewletOrActionId, badge, clazz);
if (viewletOrActionId === GLOBAL_ACTIVITY_ID) {
return this.showGlobalActivity(badge, clazz);
}
throw illegalArgument('globalActivityId');
}
private showGlobalActivity(globalActivityId: string, badge: IBadge, clazz?: string): IDisposable {
if (!badge) {
throw illegalArgument('badge');
}
const action = this.globalActivityIdToActions.get(globalActivityId);
if (!action) {
throw illegalArgument('globalActivityId');
}
action.setBadge(badge, clazz);
return toDisposable(() => action.setBadge(undefined));
private showGlobalActivity(badge: IBadge, clazz?: string): IDisposable {
this.globalActivityAction.setBadge(badge, clazz);
return toDisposable(() => this.globalActivityAction.setBadge(undefined));
}
createContentArea(parent: HTMLElement): HTMLElement {
@ -232,23 +226,19 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}
private createGlobalActivityActionBar(container: HTMLElement): void {
const activityRegistry = Registry.as<IGlobalActivityRegistry>(GlobalActivityExtensions);
const descriptors = activityRegistry.getActivities();
const actions = descriptors
.map(d => this.instantiationService.createInstance(d))
.map(a => new GlobalActivityAction(a));
this.globalActionBar = this._register(new ActionBar(container, {
this.globalActivityActionBar = this._register(new ActionBar(container, {
actionViewItemProvider: a => this.instantiationService.createInstance(GlobalActivityActionViewItem, a, (theme: ITheme) => this.getActivitybarItemColors(theme)),
orientation: ActionsOrientation.VERTICAL,
ariaLabel: nls.localize('globalActions', "Global Actions"),
ariaLabel: nls.localize('manage', "Manage"),
animated: false
}));
actions.forEach(a => {
this.globalActivityIdToActions.set(a.id, a);
this.globalActionBar.push(a);
this.globalActivityAction = new ActivityAction({
id: 'workbench.actions.manage',
name: nls.localize('manage', "Manage"),
cssClass: 'update-activity'
});
this.globalActivityActionBar.push(this.globalActivityAction);
}
private getCompositeActions(compositeId: string): { activityAction: ViewletActivityAction, pinnedAction: ToggleCompositePinnedAction } {
@ -382,8 +372,8 @@ export class ActivitybarPart extends Part implements IActivityBarService {
// Layout composite bar
let availableHeight = contentAreaSize.height;
if (this.globalActionBar) {
availableHeight -= (this.globalActionBar.viewItems.length * ActivitybarPart.ACTION_HEIGHT); // adjust height for global actions showing
if (this.globalActivityActionBar) {
availableHeight -= (this.globalActivityActionBar.viewItems.length * ActivitybarPart.ACTION_HEIGHT); // adjust height for global actions showing
}
this.compositeBar.layout(new Dimension(width, availableHeight));
}

View file

@ -25,4 +25,8 @@
.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-label.toggle-more {
-webkit-mask: url('ellipsis-global.svg') no-repeat 50% 50%;
}
.monaco-workbench .activitybar .global-activity .monaco-action-bar .action-label.update-activity {
-webkit-mask: url('update.svg') no-repeat 50% 50%;
}

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -5,7 +5,6 @@
import { Registry } from 'vs/platform/registry/common/platform';
import { IAction } from 'vs/base/common/actions';
import { IConstructorSignature0 } from 'vs/platform/instantiation/common/instantiation';
export interface IActivity {
id: string;
@ -14,31 +13,30 @@ export interface IActivity {
cssClass?: string;
}
export interface IGlobalActivity extends IActivity {
export interface IGlobalActivity {
getActions(): IAction[];
}
export const GlobalActivityExtensions = 'workbench.contributions.globalActivities';
export const GLOBAL_ACTIVITY_ID = 'workbench.action.globalActivity';
export const GlobalActivityActionsExtensions = 'workbench.contributions.globalActivityActions';
export interface IGlobalActivityRegistry {
registerActivity(descriptor: IConstructorSignature0<IGlobalActivity>): void;
getActivities(): IConstructorSignature0<IGlobalActivity>[];
registerActivity(activity: IGlobalActivity): void;
getActivities(): IGlobalActivity[];
}
export class GlobalActivityRegistry implements IGlobalActivityRegistry {
private readonly activityDescriptors = new Set<IConstructorSignature0<IGlobalActivity>>();
private readonly activities: IGlobalActivity[] = [];
registerActivity(descriptor: IConstructorSignature0<IGlobalActivity>): void {
this.activityDescriptors.add(descriptor);
registerActivity(activity: IGlobalActivity): void {
this.activities.push(activity);
}
getActivities(): IConstructorSignature0<IGlobalActivity>[] {
const result: IConstructorSignature0<IGlobalActivity>[] = [];
this.activityDescriptors.forEach(d => result.push(d));
return result;
getActivities(): IGlobalActivity[] {
return [...this.activities];
}
}
Registry.add(GlobalActivityExtensions, new GlobalActivityRegistry());
Registry.add(GlobalActivityActionsExtensions, new GlobalActivityRegistry());

View file

@ -439,4 +439,13 @@ CommandsRegistry.registerCommand({
onUnexpectedError(e);
}
}
});
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
group: '2_configuration',
command: {
id: VIEWLET_ID,
title: localize('showExtensions', "Extensions")
},
order: 2
});

View file

@ -755,6 +755,15 @@ MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, {
order: 1
});
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
group: '2_configuration',
command: {
id: SETTINGS_COMMAND_OPEN_SETTINGS,
title: nls.localize('settings', "Settings")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, {
group: '2_keybindings',
command: {
@ -764,6 +773,15 @@ MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, {
order: 1
});
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
group: '2_configuration',
command: {
id: OpenGlobalKeybindingsAction.ID,
title: nls.localize('keyboardShortcuts', "Keyboard Shortcuts")
},
order: 3
});
// Editor tool items
MenuRegistry.appendMenuItem(MenuId.EditorTitle, {

View file

@ -182,4 +182,13 @@ MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
title: nls.localize({ key: 'miGotoLine', comment: ['&& denotes a mnemonic'] }, "Go to &&Line/Column...")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
group: '1_command',
command: {
id: ShowAllCommandsAction.ID,
title: nls.localize('commandPalette', "Command Palette...")
},
order: 1
});

View file

@ -272,3 +272,12 @@ MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, {
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
group: '3_snippets',
command: {
id,
title: nls.localize('userSnippets', "User Snippets")
},
order: 1
});

View file

@ -271,3 +271,21 @@ MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, {
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
group: '4_themes',
command: {
id: SelectColorThemeAction.ID,
title: localize('selectTheme.label', "Color Theme")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
group: '4_themes',
command: {
id: SelectIconThemeAction.ID,
title: localize('themes.selectIconTheme.label', "File Icon Theme")
},
order: 2
});

View file

@ -1,8 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.update-activity {
-webkit-mask: url('update.svg') no-repeat 50% 50%;
}

View file

@ -8,7 +8,6 @@ import 'vs/platform/update/node/update.config.contribution';
import * as platform from 'vs/base/common/platform';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { IGlobalActivityRegistry, GlobalActivityExtensions } from 'vs/workbench/common/activity';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { ShowCurrentReleaseNotesAction, ProductContribution, UpdateContribution, Win3264BitContribution } from './update';
@ -24,8 +23,7 @@ if (platform.isWindows) {
}
}
Registry.as<IGlobalActivityRegistry>(GlobalActivityExtensions)
.registerActivity(UpdateContribution);
workbench.registerWorkbenchContribution(UpdateContribution, LifecyclePhase.Restored);
// Editor
Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions)

View file

@ -13,9 +13,8 @@ import product from 'vs/platform/product/node/product';
import { URI } from 'vs/base/common/uri';
import { IActivityService, NumberBadge, IBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activity';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IGlobalActivity } from 'vs/workbench/common/activity';
import { IGlobalActivity, GLOBAL_ACTIVITY_ID, IGlobalActivityRegistry, GlobalActivityActionsExtensions as GlobalActivityExtensions } from 'vs/workbench/common/activity';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IUpdateService, State as UpdateState, StateType, IUpdate } from 'vs/platform/update/common/update';
@ -27,6 +26,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
import { ReleaseNotesManager } from './releaseNotesEditor';
import { isWindows } from 'vs/base/common/platform';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { Registry } from 'vs/platform/registry/common/platform';
let releaseNotesManager: ReleaseNotesManager | undefined = undefined;
@ -212,37 +212,13 @@ export class Win3264BitContribution implements IWorkbenchContribution {
}
}
class CommandAction extends Action {
constructor(
commandId: string,
label: string,
@ICommandService commandService: ICommandService
) {
super(`command-action:${commandId}`, label, undefined, true, () => commandService.executeCommand(commandId));
}
}
export class UpdateContribution extends Disposable implements IGlobalActivity {
private static readonly showCommandsId = 'workbench.action.showCommands';
private static readonly openSettingsId = 'workbench.action.openSettings';
private static readonly openKeybindingsId = 'workbench.action.openGlobalKeybindings';
private static readonly openUserSnippets = 'workbench.action.openSnippets';
private static readonly selectColorThemeId = 'workbench.action.selectTheme';
private static readonly selectIconThemeId = 'workbench.action.selectIconTheme';
private static readonly showExtensionsId = 'workbench.view.extensions';
get id() { return 'vs.update'; }
get name() { return nls.localize('manage', "Manage"); }
get cssClass() { return 'update-activity'; }
private state: UpdateState;
private badgeDisposable: IDisposable = Disposable.None;
constructor(
@IStorageService private readonly storageService: IStorageService,
@ICommandService private readonly commandService: ICommandService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@INotificationService private readonly notificationService: INotificationService,
@IDialogService private readonly dialogService: IDialogService,
@ -272,6 +248,8 @@ export class UpdateContribution extends Disposable implements IGlobalActivity {
this.storageService.remove('update/lastKnownVersion', StorageScope.GLOBAL);
this.storageService.remove('update/updateNotificationTime', StorageScope.GLOBAL);
}
Registry.as<IGlobalActivityRegistry>(GlobalActivityExtensions).registerActivity(this);
}
private onUpdateStateChange(state: UpdateState): void {
@ -314,7 +292,7 @@ export class UpdateContribution extends Disposable implements IGlobalActivity {
this.badgeDisposable.dispose();
if (badge) {
this.badgeDisposable = this.activityService.showActivity(this.id, badge, clazz);
this.badgeDisposable = this.activityService.showActivity(GLOBAL_ACTIVITY_ID, badge, clazz);
}
this.state = state;
@ -472,19 +450,7 @@ export class UpdateContribution extends Disposable implements IGlobalActivity {
}
getActions(): IAction[] {
const result: IAction[] = [
new CommandAction(UpdateContribution.showCommandsId, nls.localize('commandPalette', "Command Palette..."), this.commandService),
new Separator(),
new CommandAction(UpdateContribution.openSettingsId, nls.localize('settings', "Settings"), this.commandService),
new CommandAction(UpdateContribution.showExtensionsId, nls.localize('showExtensions', "Extensions"), this.commandService),
new CommandAction(UpdateContribution.openKeybindingsId, nls.localize('keyboardShortcuts', "Keyboard Shortcuts"), this.commandService),
new Separator(),
new CommandAction(UpdateContribution.openUserSnippets, nls.localize('userSnippets', "User Snippets"), this.commandService),
new Separator(),
new CommandAction(UpdateContribution.selectColorThemeId, nls.localize('selectTheme.label', "Color Theme"), this.commandService),
new CommandAction(UpdateContribution.selectIconThemeId, nls.localize('themes.selectIconTheme.label', "File Icon Theme"), this.commandService)
];
const result: IAction[] = [];
const updateAction = this.getUpdateAction();
if (updateAction) {