monaco-editor
Version:
A browser based code editor
140 lines (139 loc) • 7 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ActionBar } from '../actionbar/actionbar.js';
import { DropdownMenuActionViewItem } from '../dropdown/dropdownActionViewItem.js';
import { Action, SubmenuAction } from '../../../common/actions.js';
import { Codicon } from '../../../common/codicons.js';
import { ThemeIcon } from '../../../common/themables.js';
import { EventMultiplexer } from '../../../common/event.js';
import { Disposable, DisposableStore } from '../../../common/lifecycle.js';
import './toolbar.css';
import * as nls from '../../../../nls.js';
import { createInstantHoverDelegate } from '../hover/hoverDelegateFactory.js';
/**
* A widget that combines an action bar for primary actions and a dropdown for secondary actions.
*/
export class ToolBar extends Disposable {
constructor(container, contextMenuProvider, options = { orientation: 0 /* ActionsOrientation.HORIZONTAL */ }) {
super();
this.submenuActionViewItems = [];
this.hasSecondaryActions = false;
this._onDidChangeDropdownVisibility = this._register(new EventMultiplexer());
this.onDidChangeDropdownVisibility = this._onDidChangeDropdownVisibility.event;
this.disposables = this._register(new DisposableStore());
options.hoverDelegate = options.hoverDelegate ?? this._register(createInstantHoverDelegate());
this.options = options;
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,
allowContextMenu: options.allowContextMenu,
highlightToggledItems: options.highlightToggledItems,
hoverDelegate: options.hoverDelegate,
actionViewItemProvider: (action, viewItemOptions) => {
if (action.id === ToggleMenuAction.ID) {
this.toggleMenuActionViewItem = new DropdownMenuActionViewItem(action, action.menuActions, contextMenuProvider, {
actionViewItemProvider: this.options.actionViewItemProvider,
actionRunner: this.actionRunner,
keybindingProvider: this.options.getKeyBinding,
classNames: ThemeIcon.asClassNameArray(options.moreIcon ?? Codicon.toolBarMore),
anchorAlignmentProvider: this.options.anchorAlignmentProvider,
menuAsChild: !!this.options.renderDropdownAsChildElement,
skipTelemetry: this.options.skipTelemetry,
isMenu: true,
hoverDelegate: this.options.hoverDelegate
});
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, viewItemOptions);
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: !!this.options.renderDropdownAsChildElement,
skipTelemetry: this.options.skipTelemetry,
hoverDelegate: this.options.hoverDelegate
});
result.setActionContext(this.actionBar.context);
this.submenuActionViewItems.push(result);
this.disposables.add(this._onDidChangeDropdownVisibility.add(result.onDidChangeVisibility));
return result;
}
return undefined;
}
}));
}
set actionRunner(actionRunner) {
this.actionBar.actionRunner = actionRunner;
}
get actionRunner() {
return this.actionBar.actionRunner;
}
getElement() {
return this.element;
}
getItemAction(indexOrElement) {
return this.actionBar.getAction(indexOrElement);
}
setActions(primaryActions, secondaryActions) {
this.clear();
const 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: this.options.icon ?? true, label: this.options.label ?? false, keybinding: this.getKeybindingLabel(action) });
});
}
getKeybindingLabel(action) {
const key = this.options.getKeyBinding?.(action);
return key?.getLabel() ?? undefined;
}
clear() {
this.submenuActionViewItems = [];
this.disposables.clear();
this.actionBar.clear();
}
dispose() {
this.clear();
this.disposables.dispose();
super.dispose();
}
}
export class ToggleMenuAction extends Action {
static { this.ID = 'toolbar.toggle.more'; }
constructor(toggleDropdownMenu, title) {
title = title || nls.localize('moreActions', "More Actions...");
super(ToggleMenuAction.ID, title, undefined, true);
this._menuActions = [];
this.toggleDropdownMenu = toggleDropdownMenu;
}
async run() {
this.toggleDropdownMenu();
}
get menuActions() {
return this._menuActions;
}
set menuActions(actions) {
this._menuActions = actions;
}
}