Squashed 'lib/vscode/' content from commit e5a624b788
git-subtree-dir: lib/vscode git-subtree-split: e5a624b788d92b8d34d1392e4c4d9789406efe8f
This commit is contained in:
215
src/vs/base/browser/ui/toolbar/toolbar.ts
Normal file
215
src/vs/base/browser/ui/toolbar/toolbar.ts
Normal file
@ -0,0 +1,215 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./toolbar';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Action, IActionRunner, IAction, IActionViewItemProvider, SubmenuAction } from 'vs/base/common/actions';
|
||||
import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { Codicon, registerIcon } from 'vs/base/common/codicons';
|
||||
import { EventMultiplexer } from 'vs/base/common/event';
|
||||
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem';
|
||||
import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
|
||||
|
||||
const toolBarMoreIcon = registerIcon('toolbar-more', Codicon.more);
|
||||
|
||||
export interface IToolBarOptions {
|
||||
orientation?: ActionsOrientation;
|
||||
actionViewItemProvider?: IActionViewItemProvider;
|
||||
ariaLabel?: string;
|
||||
getKeyBinding?: (action: IAction) => ResolvedKeybinding | undefined;
|
||||
actionRunner?: IActionRunner;
|
||||
toggleMenuTitle?: string;
|
||||
anchorAlignmentProvider?: () => AnchorAlignment;
|
||||
renderDropdownAsChildElement?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* A widget that combines an action bar for primary actions and a dropdown for secondary actions.
|
||||
*/
|
||||
export class ToolBar extends Disposable {
|
||||
private options: IToolBarOptions;
|
||||
private actionBar: ActionBar;
|
||||
private toggleMenuAction: ToggleMenuAction;
|
||||
private toggleMenuActionViewItem: DropdownMenuActionViewItem | undefined;
|
||||
private submenuActionViewItems: DropdownMenuActionViewItem[] = [];
|
||||
private hasSecondaryActions: boolean = false;
|
||||
private lookupKeybindings: boolean;
|
||||
private element: HTMLElement;
|
||||
|
||||
private _onDidChangeDropdownVisibility = this._register(new EventMultiplexer<boolean>());
|
||||
readonly onDidChangeDropdownVisibility = this._onDidChangeDropdownVisibility.event;
|
||||
private disposables = new DisposableStore();
|
||||
|
||||
constructor(container: HTMLElement, contextMenuProvider: IContextMenuProvider, options: IToolBarOptions = { orientation: ActionsOrientation.HORIZONTAL }) {
|
||||
super();
|
||||
|
||||
this.options = options;
|
||||
this.lookupKeybindings = typeof this.options.getKeyBinding === 'function';
|
||||
|
||||
this.toggleMenuAction = this._register(new ToggleMenuAction(() => this.toggleMenuActionViewItem?.show(), options.toggleMenuTitle));
|
||||
|
||||
this.element = document.createElement('div');
|
||||
this.element.className = 'monaco-toolbar';
|
||||
container.appendChild(this.element);
|
||||
|
||||
this.actionBar = this._register(new ActionBar(this.element, {
|
||||
orientation: options.orientation,
|
||||
ariaLabel: options.ariaLabel,
|
||||
actionRunner: options.actionRunner,
|
||||
actionViewItemProvider: (action: IAction) => {
|
||||
if (action.id === ToggleMenuAction.ID) {
|
||||
this.toggleMenuActionViewItem = new DropdownMenuActionViewItem(
|
||||
action,
|
||||
(<ToggleMenuAction>action).menuActions,
|
||||
contextMenuProvider,
|
||||
{
|
||||
actionViewItemProvider: this.options.actionViewItemProvider,
|
||||
actionRunner: this.actionRunner,
|
||||
keybindingProvider: this.options.getKeyBinding,
|
||||
classNames: toolBarMoreIcon.classNamesArray,
|
||||
anchorAlignmentProvider: this.options.anchorAlignmentProvider,
|
||||
menuAsChild: !!this.options.renderDropdownAsChildElement
|
||||
}
|
||||
);
|
||||
this.toggleMenuActionViewItem.setActionContext(this.actionBar.context);
|
||||
this.disposables.add(this._onDidChangeDropdownVisibility.add(this.toggleMenuActionViewItem.onDidChangeVisibility));
|
||||
|
||||
return this.toggleMenuActionViewItem;
|
||||
}
|
||||
|
||||
if (options.actionViewItemProvider) {
|
||||
const result = options.actionViewItemProvider(action);
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (action instanceof SubmenuAction) {
|
||||
const result = new DropdownMenuActionViewItem(
|
||||
action,
|
||||
action.actions,
|
||||
contextMenuProvider,
|
||||
{
|
||||
actionViewItemProvider: this.options.actionViewItemProvider,
|
||||
actionRunner: this.actionRunner,
|
||||
keybindingProvider: this.options.getKeyBinding,
|
||||
classNames: action.class,
|
||||
anchorAlignmentProvider: this.options.anchorAlignmentProvider,
|
||||
menuAsChild: true
|
||||
}
|
||||
);
|
||||
result.setActionContext(this.actionBar.context);
|
||||
this.submenuActionViewItems.push(result);
|
||||
this.disposables.add(this._onDidChangeDropdownVisibility.add(result.onDidChangeVisibility));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
set actionRunner(actionRunner: IActionRunner) {
|
||||
this.actionBar.actionRunner = actionRunner;
|
||||
}
|
||||
|
||||
get actionRunner(): IActionRunner {
|
||||
return this.actionBar.actionRunner;
|
||||
}
|
||||
|
||||
set context(context: unknown) {
|
||||
this.actionBar.context = context;
|
||||
if (this.toggleMenuActionViewItem) {
|
||||
this.toggleMenuActionViewItem.setActionContext(context);
|
||||
}
|
||||
for (const actionViewItem of this.submenuActionViewItems) {
|
||||
actionViewItem.setActionContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
getElement(): HTMLElement {
|
||||
return this.element;
|
||||
}
|
||||
|
||||
getItemsWidth(): number {
|
||||
let itemsWidth = 0;
|
||||
for (let i = 0; i < this.actionBar.length(); i++) {
|
||||
itemsWidth += this.actionBar.getWidth(i);
|
||||
}
|
||||
return itemsWidth;
|
||||
}
|
||||
|
||||
setAriaLabel(label: string): void {
|
||||
this.actionBar.setAriaLabel(label);
|
||||
}
|
||||
|
||||
setActions(primaryActions: ReadonlyArray<IAction>, secondaryActions?: ReadonlyArray<IAction>): void {
|
||||
this.clear();
|
||||
|
||||
let primaryActionsToSet = primaryActions ? primaryActions.slice(0) : [];
|
||||
|
||||
// Inject additional action to open secondary actions if present
|
||||
this.hasSecondaryActions = !!(secondaryActions && secondaryActions.length > 0);
|
||||
if (this.hasSecondaryActions && secondaryActions) {
|
||||
this.toggleMenuAction.menuActions = secondaryActions.slice(0);
|
||||
primaryActionsToSet.push(this.toggleMenuAction);
|
||||
}
|
||||
|
||||
primaryActionsToSet.forEach(action => {
|
||||
this.actionBar.push(action, { icon: true, label: false, keybinding: this.getKeybindingLabel(action) });
|
||||
});
|
||||
}
|
||||
|
||||
private getKeybindingLabel(action: IAction): string | undefined {
|
||||
const key = this.lookupKeybindings ? this.options.getKeyBinding?.(action) : undefined;
|
||||
|
||||
return withNullAsUndefined(key?.getLabel());
|
||||
}
|
||||
|
||||
private clear(): void {
|
||||
this.submenuActionViewItems = [];
|
||||
this.disposables.clear();
|
||||
this.actionBar.clear();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.clear();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class ToggleMenuAction extends Action {
|
||||
|
||||
static readonly ID = 'toolbar.toggle.more';
|
||||
|
||||
private _menuActions: ReadonlyArray<IAction>;
|
||||
private toggleDropdownMenu: () => void;
|
||||
|
||||
constructor(toggleDropdownMenu: () => void, title?: string) {
|
||||
title = title || nls.localize('moreActions', "More Actions...");
|
||||
super(ToggleMenuAction.ID, title, undefined, true);
|
||||
|
||||
this._menuActions = [];
|
||||
this.toggleDropdownMenu = toggleDropdownMenu;
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
this.toggleDropdownMenu();
|
||||
}
|
||||
|
||||
get menuActions(): ReadonlyArray<IAction> {
|
||||
return this._menuActions;
|
||||
}
|
||||
|
||||
set menuActions(actions: ReadonlyArray<IAction>) {
|
||||
this._menuActions = actions;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user