Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow More Actions... button on configurable toolbars to be hidden #241268

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/vs/base/browser/ui/toolbar/toolbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ export interface IToolBarOptions {
export class ToolBar extends Disposable {
private options: IToolBarOptions;
protected readonly actionBar: ActionBar;
private toggleMenuAction: ToggleMenuAction;
protected readonly toggleMenuAction: ToggleMenuAction;
private toggleMenuActionViewItem: DropdownMenuActionViewItem | undefined;
private submenuActionViewItems: DropdownMenuActionViewItem[] = [];
private hasSecondaryActions: boolean = false;
protected isToggleMenuHidden: boolean = false;
private readonly element: HTMLElement;

private _onDidChangeDropdownVisibility = this._register(new EventMultiplexer<boolean>());
Expand Down Expand Up @@ -200,7 +201,7 @@ export class ToolBar extends Disposable {

// Inject additional action to open secondary actions if present
this.hasSecondaryActions = !!(secondaryActions && secondaryActions.length > 0);
if (this.hasSecondaryActions && secondaryActions) {
if (this.hasSecondaryActions && secondaryActions && !this.isToggleMenuHidden) {
this.toggleMenuAction.menuActions = secondaryActions.slice(0);
primaryActionsToSet.push(this.toggleMenuAction);
}
Expand Down
58 changes: 56 additions & 2 deletions src/vs/platform/actions/browser/toolbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ export class WorkbenchToolBar extends ToolBar {

private readonly _sessionDisposables = this._store.add(new DisposableStore());

private _primaryActions: ReadonlyArray<IAction> = [];
private _secondaryActions: ReadonlyArray<IAction> | undefined;
private _menuIds: readonly MenuId[] | undefined;
private readonly _resetMenu: MenuId | undefined;

constructor(
container: HTMLElement,
private _options: IWorkbenchToolBarOptions | undefined,
Expand All @@ -108,6 +113,11 @@ export class WorkbenchToolBar extends ToolBar {
skipTelemetry: typeof _options?.telemetrySource === 'string',
});

if (_options?.resetMenu) {
this._resetMenu = _options.resetMenu;
this.isToggleMenuHidden = this._menuService.getHiddenState(this._resetMenu, this.toggleMenuAction.id);
}

// telemetry logic
const telemetrySource = _options?.telemetrySource;
if (telemetrySource) {
Expand All @@ -119,7 +129,9 @@ export class WorkbenchToolBar extends ToolBar {
}

override setActions(_primary: readonly IAction[], _secondary: readonly IAction[] = [], menuIds?: readonly MenuId[]): void {

this._primaryActions = _primary;
this._secondaryActions = _secondary;
this._menuIds = menuIds;
this._sessionDisposables.clear();
const primary: Array<IAction | undefined> = _primary.slice(); // for hiding and overflow we set some items to undefined
const secondary = _secondary.slice();
Expand Down Expand Up @@ -200,6 +212,12 @@ export class WorkbenchToolBar extends ToolBar {

const primaryActions = [];

// More Actions... submenu if dedicated button has been hidden
if (this.isToggleMenuHidden && (secondary.length + extraSecondary.length) > 0) {
primaryActions.push(new SubmenuAction(ToggleMenuAction.ID, this.toggleMenuAction.label, Separator.join(extraSecondary, secondary)));
primaryActions.push(new Separator());
}

// -- Configure Keybinding Action --
if (action instanceof MenuItemAction && action.menuKeybinding) {
primaryActions.push(action.menuKeybinding);
Expand Down Expand Up @@ -239,6 +257,19 @@ export class WorkbenchToolBar extends ToolBar {
}
primaryActions.push(action.hideActions.hide);

} else if (action instanceof ToggleMenuAction && primary.length > 0 && this._resetMenu) {
// Only offered if caller provided a reset menu (to persist state on) and at least one primary button remains (from which to access Show 'More Actions...')
primaryActions.push(toAction({
id: 'label',
label: localize('hideToggleMenu', 'Hide \'{0}\'', action.label),
run: () => {
this.isToggleMenuHidden = true;
if (this._resetMenu) {
this._menuService.setHiddenState(this._resetMenu, this.toggleMenuAction.id, true);
}
this.setActions(this._primaryActions, this._secondaryActions, this._menuIds);
}
}));
} else {
primaryActions.push(toAction({
id: 'label',
Expand All @@ -251,12 +282,35 @@ export class WorkbenchToolBar extends ToolBar {

const actions = Separator.join(primaryActions, toggleActions);

// Add option to show the More Actions button if it is hidden
let separatorAdded = false;
if (secondary.length + extraSecondary.length > 0) {
if (this.isToggleMenuHidden) {
actions.push(new Separator());
separatorAdded = true;
actions.push(toAction({
id: 'showToggleMenu',
label: localize('showToggleMenu', 'Show \'{0}\'', this.toggleMenuAction.label),
run: () => {
this.isToggleMenuHidden = false;
if (this._resetMenu) {
this._menuService.setHiddenState(this._resetMenu, this.toggleMenuAction.id, false);
}
this.setActions(this._primaryActions, this._secondaryActions, this._menuIds);
}
}));
}
}

// add "Reset Menu" action
if (this._options?.resetMenu && !menuIds) {
menuIds = [this._options.resetMenu];
}
if (someAreHidden && menuIds) {
actions.push(new Separator());
if (!separatorAdded) {
actions.push(new Separator());
separatorAdded = true;
}
actions.push(toAction({
id: 'resetThisMenu',
label: localize('resetThisMenu', "Reset Menu"),
Expand Down
10 changes: 10 additions & 0 deletions src/vs/platform/actions/common/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,16 @@ export interface IMenuService {
* Reset the menu's hidden states.
*/
resetHiddenStates(menuIds: readonly MenuId[] | undefined): void;

/**
* Get the hidden state of a menu item.
*/
getHiddenState(id: MenuId, commandId: string): boolean;

/**
* Set the hidden state of a menu item.
*/
setHiddenState(id: MenuId, commandId: string, value: boolean): void;
}

type ICommandsMap = Map<string, ICommandAction>;
Expand Down
8 changes: 8 additions & 0 deletions src/vs/platform/actions/common/menuService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ export class MenuService implements IMenuService {
resetHiddenStates(ids?: MenuId[]): void {
this._hiddenStates.reset(ids);
}

getHiddenState(id: MenuId, commandId: string): boolean {
return this._hiddenStates.isHidden(id, commandId);
}

setHiddenState(id: MenuId, commandId: string, value: boolean): void {
this._hiddenStates.updateHidden(id, commandId, value);
}
}

class PersistedMenuHideState {
Expand Down
7 changes: 7 additions & 0 deletions src/vs/workbench/test/browser/workbenchTestServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,13 @@ export class TestMenuService implements IMenuService {
resetHiddenStates(): void {
// nothing
}
getHiddenState(id: MenuId, commandId: string): boolean {
return false;
}

setHiddenState(id: MenuId, commandId: string, value: boolean): void {
// nothing
}
}

export class TestFileDialogService implements IFileDialogService {
Expand Down