@jupyterlab/ui-components
Version:
JupyterLab - UI components written in React
297 lines • 8.39 kB
JavaScript
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
/* global WeakRef */
import { ArrayExt } from '@lumino/algorithm';
import { DisposableDelegate } from '@lumino/disposable';
import { Signal } from '@lumino/signaling';
import { Menu } from '@lumino/widgets';
/**
* Namespace for JupyterLabMenu interfaces
*/
export var IRankedMenu;
(function (IRankedMenu) {
/**
* Default menu item rank
*/
IRankedMenu.DEFAULT_RANK = 100;
})(IRankedMenu || (IRankedMenu = {}));
/**
* An extensible menu for JupyterLab application menus.
*/
export class RankedMenu extends Menu {
/**
* Construct a new menu.
*
* @param options - Options for the lumino menu.
*/
constructor(options) {
var _a;
super(options);
this._ranks = [];
this.addClass('jp-ThemedContainer');
this._rank = options.rank;
this._includeSeparators = (_a = options.includeSeparators) !== null && _a !== void 0 ? _a : true;
}
/**
* Menu rank.
*/
get rank() {
return this._rank;
}
/**
* Add a group of menu items specific to a particular
* plugin.
*
* The rank can be set for all items in the group using the
* function argument or per item.
*
* @param items - the list of menu items to add.
* @param rank - the default rank in the menu in which to insert the group.
* @returns Disposable of the group
*/
addGroup(items, rank) {
if (items.length === 0) {
return new DisposableDelegate(() => void 0);
}
const defaultRank = rank !== null && rank !== void 0 ? rank : IRankedMenu.DEFAULT_RANK;
const sortedItems = items
.map(item => {
var _a;
return { ...item, rank: (_a = item.rank) !== null && _a !== void 0 ? _a : defaultRank };
})
.sort((a, b) => a.rank - b.rank);
// Insert the plugin group into the menu.
let insertIndex = this._ranks.findIndex(rank => sortedItems[0].rank < rank);
if (insertIndex < 0) {
insertIndex = this._ranks.length; // Insert at the end of the menu
}
// Keep an array of the menu items that have been created.
const added = [];
// Insert a separator before the group.
// Lumino takes care of superfluous leading,
// trailing, and duplicate separators.
if (this._includeSeparators) {
added.push(this.insertItem(insertIndex++, { type: 'separator', rank: defaultRank }));
}
// Insert the group.
added.push(...sortedItems.map(item => {
return this.insertItem(insertIndex++, item);
}));
// Insert a separator after the group.
if (this._includeSeparators) {
added.push(this.insertItem(insertIndex++, { type: 'separator', rank: defaultRank }));
}
return new DisposableDelegate(() => {
added.forEach(i => i.dispose());
});
}
/**
* Add a menu item to the end of the menu.
*
* @param options - The options for creating the menu item.
*
* @returns The menu item added to the menu.
*/
addItem(options) {
let insertIndex = -1;
if (options.rank) {
insertIndex = this._ranks.findIndex(rank => options.rank < rank);
}
if (insertIndex < 0) {
insertIndex = this._ranks.length; // Insert at the end of the menu
}
return this.insertItem(insertIndex, options);
}
/**
* Remove all menu items from the menu.
*/
clearItems() {
this._ranks.length = 0;
super.clearItems();
}
/**
* Dispose of the resources held by the menu.
*/
dispose() {
this._ranks.length = 0;
super.dispose();
}
/**
* Get the rank of the item at index.
*
* @param index Item index.
* @returns Rank of the item.
*/
getRankAt(index) {
return this._ranks[index];
}
/**
* Insert a menu item into the menu at the specified index.
*
* @param index - The index at which to insert the item.
*
* @param options - The options for creating the menu item.
*
* @returns The menu item added to the menu.
*
* #### Notes
* The index will be clamped to the bounds of the items.
*/
insertItem(index, options) {
var _a, _b;
const clampedIndex = Math.max(0, Math.min(index, this._ranks.length));
ArrayExt.insert(this._ranks, clampedIndex, (_a = options.rank) !== null && _a !== void 0 ? _a : Math.max(IRankedMenu.DEFAULT_RANK, (_b = this._ranks[this._ranks.length - 1]) !== null && _b !== void 0 ? _b : IRankedMenu.DEFAULT_RANK));
const item = super.insertItem(clampedIndex, options);
return new DisposableMenuItem(item, this);
}
/**
* Remove the item at a given index from the menu.
*
* @param index - The index of the item to remove.
*
* #### Notes
* This is a no-op if the index is out of range.
*/
removeItemAt(index) {
ArrayExt.removeAt(this._ranks, index);
super.removeItemAt(index);
}
}
/**
* Disposable Menu Item
*/
class DisposableMenuItem {
/**
* Create a disposable menu item from an item and the menu it belongs to
*
* @param item Menu item
* @param menu Menu
*/
constructor(item, menu) {
this._item = new WeakRef(item);
this._menu = menu;
// dispose this item if the parent menu is disposed
const dispose = (menu) => {
menu.disposed.disconnect(dispose, this);
this.dispose();
};
this._menu.disposed.connect(dispose, this);
}
/**
* Whether the menu item is disposed or not.
*/
get isDisposed() {
return this._isDisposed;
}
/**
* The type of the menu item.
*/
get type() {
return this._item.deref().type;
}
/**
* The command to execute when the item is triggered.
*/
get command() {
return this._item.deref().command;
}
/**
* The arguments for the command.
*/
get args() {
return this._item.deref().args;
}
/**
* The submenu for a `'submenu'` type item.
*/
get submenu() {
return this._item.deref().submenu;
}
/**
* The display label for the menu item.
*/
get label() {
return this._item.deref().label;
}
/**
* The mnemonic index for the menu item.
*/
get mnemonic() {
return this._item.deref().mnemonic;
}
/**
* The icon renderer for the menu item.
*/
get icon() {
return this._item.deref().icon;
}
/**
* The icon class for the menu item.
*/
get iconClass() {
return this._item.deref().iconClass;
}
/**
* The icon label for the menu item.
*/
get iconLabel() {
return this._item.deref().iconLabel;
}
/**
* The display caption for the menu item.
*/
get caption() {
return this._item.deref().caption;
}
/**
* The extra class name for the menu item.
*/
get className() {
return this._item.deref().className;
}
/**
* The dataset for the menu item.
*/
get dataset() {
return this._item.deref().dataset;
}
/**
* Whether the menu item is enabled.
*/
get isEnabled() {
return this._item.deref().isEnabled;
}
/**
* Whether the menu item is toggled.
*/
get isToggled() {
return this._item.deref().isToggled;
}
/**
* Whether the menu item is visible.
*/
get isVisible() {
return this._item.deref().isVisible;
}
/**
* The key binding for the menu item.
*/
get keyBinding() {
return this._item.deref().keyBinding;
}
/**
* Dispose the menu item by removing it from its menu.
*/
dispose() {
if (this._isDisposed) {
return;
}
this._isDisposed = true;
const item = this._item.deref();
if (item && !this._menu.isDisposed) {
this._menu.removeItem(item);
}
Signal.clearData(this);
}
}
//# sourceMappingURL=menu.js.map