UNPKG

@theia/core

Version:

Theia is a cloud & desktop IDE framework implemented in TypeScript.

418 lines • 19.5 kB
"use strict"; // ***************************************************************************** // Copyright (C) 2018 TypeFox and others. // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License v. 2.0 which is available at // http://www.eclipse.org/legal/epl-2.0. // // This Source Code may also be made available under the following Secondary // Licenses when the conditions for such availability set forth in the Eclipse // Public License v. 2.0 are satisfied: GNU General Public License, version 2 // with the GNU Classpath Exception which is available at // https://www.gnu.org/software/classpath/license.html. // // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var TabBarToolbar_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.TabBarToolbar = exports.TabBarToolbarFactory = void 0; const inversify_1 = require("inversify"); const React = require("react"); const context_key_service_1 = require("../../context-key-service"); const common_1 = require("../../../common"); const context_menu_renderer_1 = require("../../context-menu-renderer"); const label_parser_1 = require("../../label-parser"); const widgets_1 = require("../../widgets"); const tab_bar_toolbar_registry_1 = require("./tab-bar-toolbar-registry"); const tab_bar_toolbar_types_1 = require("./tab-bar-toolbar-types"); const keybinding_1 = require("../..//keybinding"); /** * Factory for instantiating tab-bar toolbars. */ exports.TabBarToolbarFactory = Symbol('TabBarToolbarFactory'); /** * Class name indicating rendering of a toolbar item without an icon but instead with a text label. */ const NO_ICON_CLASS = 'no-icon'; /** * Tab-bar toolbar widget representing the active [tab-bar toolbar items](TabBarToolbarItem). */ let TabBarToolbar = TabBarToolbar_1 = class TabBarToolbar extends widgets_1.ReactWidget { constructor() { super(); this.inline = new Map(); this.more = new Map(); this.toDisposeOnUpdateItems = new common_1.DisposableCollection(); this.keybindingContextKeys = new Set(); this.toDisposeOnSetCurrent = new common_1.DisposableCollection(); this.showMoreContextMenu = (event) => { event.stopPropagation(); event.preventDefault(); const anchor = this.toAnchor(event); this.renderMoreContextMenu(anchor); }; /** * Presents the menu to popup on the `event` that is the clicking of * a menu toolbar item. * * @param menuPath the path of the registered menu to show * @param event the mouse event triggering the menu */ this.showPopupMenu = (menuPath, event) => { event.stopPropagation(); event.preventDefault(); const anchor = this.toAnchor(event); this.renderPopupMenu(menuPath, anchor); }; this.executeCommand = (e) => { e.preventDefault(); e.stopPropagation(); const item = this.inline.get(e.currentTarget.id); if (!item || !this.isEnabled(item)) { return; } if (item.command && item.menuPath) { this.menuCommandExecutor.executeCommand(item.menuPath, item.command, this.current); } else if (item.command) { this.commands.executeCommand(item.command, this.current); } else if (item.menuPath) { this.renderMoreContextMenu(this.toAnchor(e), item.menuPath); } this.update(); }; this.onMouseDownEvent = (e) => { if (e.button === 0) { e.currentTarget.classList.add('active'); } }; this.onMouseUpEvent = (e) => { e.currentTarget.classList.remove('active'); }; this.addClass(TabBarToolbar_1.Styles.TAB_BAR_TOOLBAR); this.hide(); } init() { this.toDispose.push(this.keybindings.onKeybindingsChanged(() => this.update())); this.toDispose.push(this.contextKeyService.onDidChange(e => { if (e.affects(this.keybindingContextKeys)) { this.update(); } })); } updateItems(items, current) { var _a; this.toDisposeOnUpdateItems.dispose(); this.toDisposeOnUpdateItems = new common_1.DisposableCollection(); this.inline.clear(); this.more.clear(); const contextKeys = new Set(); for (const item of items.sort(tab_bar_toolbar_types_1.TabBarToolbarItem.PRIORITY_COMPARATOR).reverse()) { if ('command' in item) { this.commands.getAllHandlers(item.command).forEach(handler => { if (handler.onDidChangeEnabled) { this.toDisposeOnUpdateItems.push(handler.onDidChangeEnabled(() => this.update())); } }); } if ('render' in item || item.group === undefined || item.group === 'navigation') { this.inline.set(item.id, item); } else { this.more.set(item.id, item); } if (item.when) { (_a = this.contextKeyService.parseKeys(item.when)) === null || _a === void 0 ? void 0 : _a.forEach(key => contextKeys.add(key)); } } this.updateContextKeyListener(contextKeys); this.setCurrent(current); if (items.length) { this.show(); } else { this.hide(); } this.update(); } updateTarget(current) { const operativeWidget = tab_bar_toolbar_types_1.TabBarDelegator.is(current) ? current.getTabBarDelegate() : current; const items = operativeWidget ? this.toolbarRegistry.visibleItems(operativeWidget) : []; this.updateItems(items, operativeWidget); } setCurrent(current) { this.toDisposeOnSetCurrent.dispose(); this.toDispose.push(this.toDisposeOnSetCurrent); this.current = current; if (current) { const resetCurrent = () => { this.setCurrent(undefined); this.update(); }; current.disposed.connect(resetCurrent); this.toDisposeOnSetCurrent.push(common_1.Disposable.create(() => current.disposed.disconnect(resetCurrent))); } } updateContextKeyListener(contextKeys) { var _a; (_a = this.contextKeyListener) === null || _a === void 0 ? void 0 : _a.dispose(); if (contextKeys.size > 0) { this.contextKeyListener = this.contextKeyService.onDidChange(event => { if (event.affects(contextKeys)) { this.update(); } }); } } render() { this.keybindingContextKeys.clear(); return React.createElement(React.Fragment, null, this.renderMore(), [...this.inline.values()].map(item => tab_bar_toolbar_types_1.TabBarToolbarItem.is(item) ? (tab_bar_toolbar_types_1.MenuToolbarItem.is(item) && !item.command ? this.renderMenuItem(item) : this.renderItem(item)) : item.render(this.current))); } resolveKeybindingForCommand(command) { let result = ''; if (command) { const bindings = this.keybindings.getKeybindingsForCommand(command); let found = false; if (bindings && bindings.length > 0) { bindings.forEach(binding => { var _a, _b; if (binding.when) { (_a = this.contextKeyService.parseKeys(binding.when)) === null || _a === void 0 ? void 0 : _a.forEach(key => this.keybindingContextKeys.add(key)); } if (!found && this.keybindings.isEnabledInScope(binding, (_b = this.current) === null || _b === void 0 ? void 0 : _b.node)) { found = true; result = ` (${this.keybindings.acceleratorFor(binding, '+')})`; } }); } } return result; } renderItem(item) { let innerText = ''; const classNames = []; const command = item.command ? this.commands.getCommand(item.command) : undefined; // Fall back to the item ID in extremis so there is _something_ to render in the // case that there is neither an icon nor a title const itemText = item.text || (command === null || command === void 0 ? void 0 : command.label) || (command === null || command === void 0 ? void 0 : command.id) || item.id; if (itemText) { for (const labelPart of this.labelParser.parse(itemText)) { if (label_parser_1.LabelIcon.is(labelPart)) { const className = `fa fa-${labelPart.name}${labelPart.animation ? ' fa-' + labelPart.animation : ''}`; classNames.push(...className.split(' ')); } else { innerText = labelPart; } } } const iconClass = (typeof item.icon === 'function' && item.icon()) || item.icon || (command && command.iconClass); if (iconClass) { classNames.push(iconClass); } const tooltipText = item.tooltip || (command && command.label) || ''; const tooltip = `${this.labelParser.stripIcons(tooltipText)}${this.resolveKeybindingForCommand(command === null || command === void 0 ? void 0 : command.id)}`; // Only present text if there is no icon if (classNames.length) { innerText = ''; } else if (innerText) { // Make room for the label text classNames.push(NO_ICON_CLASS); } // In any case, this is an action item, with or without icon. classNames.push(widgets_1.ACTION_ITEM); const toolbarItemClassNames = this.getToolbarItemClassNames(item); return React.createElement("div", { key: item.id, className: toolbarItemClassNames.join(' '), onMouseDown: this.onMouseDownEvent, onMouseUp: this.onMouseUpEvent, onMouseOut: this.onMouseUpEvent }, React.createElement("div", { id: item.id, className: classNames.join(' '), onClick: this.executeCommand, title: tooltip }, innerText)); } isEnabled(item) { if (!!item.command) { return this.commandIsEnabled(item.command) && this.evaluateWhenClause(item.when); } else { return !!item.menuPath; } } getToolbarItemClassNames(item) { const classNames = [TabBarToolbar_1.Styles.TAB_BAR_TOOLBAR_ITEM]; if (item.command) { if (this.isEnabled(item)) { classNames.push('enabled'); } if (this.commandIsToggled(item.command)) { classNames.push('toggled'); } } else { if (this.isEnabled(item)) { classNames.push('enabled'); } } return classNames; } renderMore() { return !!this.more.size && React.createElement("div", { key: '__more__', className: TabBarToolbar_1.Styles.TAB_BAR_TOOLBAR_ITEM + ' enabled' }, React.createElement("div", { id: '__more__', className: (0, widgets_1.codicon)('ellipsis', true), onClick: this.showMoreContextMenu, title: common_1.nls.localizeByDefault('More Actions...') })); } toAnchor(event) { var _a; const itemBox = (_a = event.currentTarget.closest('.' + TabBarToolbar_1.Styles.TAB_BAR_TOOLBAR_ITEM)) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect(); return itemBox ? { y: itemBox.bottom, x: itemBox.left } : event.nativeEvent; } renderMoreContextMenu(anchor, subpath) { var _a, _b; const toDisposeOnHide = new common_1.DisposableCollection(); this.addClass('menu-open'); toDisposeOnHide.push(common_1.Disposable.create(() => this.removeClass('menu-open'))); if (subpath) { toDisposeOnHide.push(this.menus.linkSubmenu(tab_bar_toolbar_types_1.TAB_BAR_TOOLBAR_CONTEXT_MENU, subpath)); } else { for (const item of this.more.values()) { if (item.menuPath && !item.command) { toDisposeOnHide.push(this.menus.linkSubmenu(tab_bar_toolbar_types_1.TAB_BAR_TOOLBAR_CONTEXT_MENU, item.menuPath, undefined, item.group)); } else if (item.command) { // Register a submenu for the item, if the group is in format `<submenu group>/<submenu name>/.../<item group>` if ((_a = item.group) === null || _a === void 0 ? void 0 : _a.includes('/')) { const split = item.group.split('/'); const paths = []; for (let i = 0; i < split.length - 1; i += 2) { paths.push(split[i], split[i + 1]); toDisposeOnHide.push(this.menus.registerSubmenu([...tab_bar_toolbar_types_1.TAB_BAR_TOOLBAR_CONTEXT_MENU, ...paths], split[i + 1], { order: item.order })); } } toDisposeOnHide.push(this.menus.registerMenuAction([...tab_bar_toolbar_types_1.TAB_BAR_TOOLBAR_CONTEXT_MENU, ...item.group.split('/')], { label: item.tooltip, commandId: item.command, when: item.when, order: item.order, })); } } } return this.contextMenuRenderer.render({ menuPath: tab_bar_toolbar_types_1.TAB_BAR_TOOLBAR_CONTEXT_MENU, args: [this.current], anchor, context: (_b = this.current) === null || _b === void 0 ? void 0 : _b.node, onHide: () => toDisposeOnHide.dispose(), skipSingleRootNode: true, }); } /** * Renders a toolbar item that is a menu, presenting it as a button with a little * chevron decoration that pops up a floating menu when clicked. * * @param item a toolbar item that is a menu item * @returns the rendered toolbar item */ renderMenuItem(item) { var _a; const icon = typeof item.icon === 'function' ? item.icon() : (_a = item.icon) !== null && _a !== void 0 ? _a : 'ellipsis'; return React.createElement("div", { key: item.id, className: TabBarToolbar_1.Styles.TAB_BAR_TOOLBAR_ITEM + ' enabled menu', onClick: this.showPopupMenu.bind(this, item.menuPath) }, React.createElement("div", { id: item.id, className: (0, widgets_1.codicon)(icon, true), title: item.text }), React.createElement("div", { className: (0, widgets_1.codicon)('chevron-down') + ' chevron' })); } /** * Renders the menu popped up on a menu toolbar item. * * @param menuPath the path of the registered menu to render * @param anchor a description of where to render the menu * @returns platform-specific access to the rendered context menu */ renderPopupMenu(menuPath, anchor) { var _a; const toDisposeOnHide = new common_1.DisposableCollection(); this.addClass('menu-open'); toDisposeOnHide.push(common_1.Disposable.create(() => this.removeClass('menu-open'))); return this.contextMenuRenderer.render({ menuPath, args: [this.current], anchor, context: (_a = this.current) === null || _a === void 0 ? void 0 : _a.node, onHide: () => toDisposeOnHide.dispose() }); } shouldHandleMouseEvent(event) { return event.target instanceof Element && this.node.contains(event.target); } commandIsEnabled(command) { return this.commands.isEnabled(command, this.current); } commandIsToggled(command) { return this.commands.isToggled(command, this.current); } evaluateWhenClause(whenClause) { var _a; return whenClause ? this.contextKeyService.match(whenClause, (_a = this.current) === null || _a === void 0 ? void 0 : _a.node) : true; } }; __decorate([ (0, inversify_1.inject)(common_1.CommandRegistry), __metadata("design:type", common_1.CommandRegistry) ], TabBarToolbar.prototype, "commands", void 0); __decorate([ (0, inversify_1.inject)(label_parser_1.LabelParser), __metadata("design:type", label_parser_1.LabelParser) ], TabBarToolbar.prototype, "labelParser", void 0); __decorate([ (0, inversify_1.inject)(common_1.MenuModelRegistry), __metadata("design:type", common_1.MenuModelRegistry) ], TabBarToolbar.prototype, "menus", void 0); __decorate([ (0, inversify_1.inject)(common_1.MenuCommandExecutor), __metadata("design:type", Object) ], TabBarToolbar.prototype, "menuCommandExecutor", void 0); __decorate([ (0, inversify_1.inject)(context_menu_renderer_1.ContextMenuRenderer), __metadata("design:type", context_menu_renderer_1.ContextMenuRenderer) ], TabBarToolbar.prototype, "contextMenuRenderer", void 0); __decorate([ (0, inversify_1.inject)(tab_bar_toolbar_registry_1.TabBarToolbarRegistry), __metadata("design:type", tab_bar_toolbar_registry_1.TabBarToolbarRegistry) ], TabBarToolbar.prototype, "toolbarRegistry", void 0); __decorate([ (0, inversify_1.inject)(context_key_service_1.ContextKeyService), __metadata("design:type", Object) ], TabBarToolbar.prototype, "contextKeyService", void 0); __decorate([ (0, inversify_1.inject)(keybinding_1.KeybindingRegistry), __metadata("design:type", keybinding_1.KeybindingRegistry) ], TabBarToolbar.prototype, "keybindings", void 0); __decorate([ (0, inversify_1.postConstruct)(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], TabBarToolbar.prototype, "init", null); TabBarToolbar = TabBarToolbar_1 = __decorate([ (0, inversify_1.injectable)(), __metadata("design:paramtypes", []) ], TabBarToolbar); exports.TabBarToolbar = TabBarToolbar; (function (TabBarToolbar) { let Styles; (function (Styles) { Styles.TAB_BAR_TOOLBAR = 'p-TabBar-toolbar'; Styles.TAB_BAR_TOOLBAR_ITEM = 'item'; })(Styles = TabBarToolbar.Styles || (TabBarToolbar.Styles = {})); })(TabBarToolbar = exports.TabBarToolbar || (exports.TabBarToolbar = {})); exports.TabBarToolbar = TabBarToolbar; //# sourceMappingURL=tab-bar-toolbar.js.map