Skip to content

Commit

Permalink
Helper buttons are now configurable (#18)
Browse files Browse the repository at this point in the history
Fixes #17
  • Loading branch information
fcollonval authored Apr 10, 2021
1 parent 0853ad5 commit fbe085a
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 71 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ A cell toolbar for JupyterLab.
![Demonstration](https://raw.githubusercontent.com/jupyterlab-contrib/jlab-enhanced-cell-toolbar/main/docs/default_look.png)

There are some [Settings](#Settings) to tune the available buttons and the look of this extension.
For example, to show only the tags, you can set the following settings:

```json
{
"helperButtons": null,
"leftMenu": null,
"rightMenu": null
}
```

## Requirements

Expand Down Expand Up @@ -54,6 +63,17 @@ conda remove -c conda-forge jlab-enhanced-cell-toolbar

![default tags](https://raw.githubusercontent.com/jupyterlab-contrib/jlab-enhanced-cell-toolbar/main/docs/default_tags.png)


- _helperButtons_: The list of helper buttons to display. For example, using the following settings:

```json
{
"helperButtons": [ "insert-cell-below", "run-cell-and-select-next"]
}
```

![helper buttons](https://raw.githubusercontent.com/jupyterlab-contrib/jlab-enhanced-cell-toolbar/main/docs/helper_buttons.png)

- _leftMenu_ and _rightMenu_: The action buttons to be displayed on the left and right of the cell toolbar. For example, using the following settings:

```json
Expand Down
Binary file added docs/helper_buttons.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@jlab-enhanced/cell-toolbar",
"version": "3.1.1",
"version": "3.2.0",
"description": "A cell toolbar for JupyterLab.",
"keywords": [
"jupyter",
Expand Down
28 changes: 28 additions & 0 deletions schema/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,34 @@
"pattern": "^[\\w-]+$"
}
},
"helperButtons": {
"title": "Helper buttons",
"description": "Set the list of visible helper buttons.",
"default": [
"insert-cell-below",
"move-cell-down",
"move-cell-up",
"run-cell-and-select-next"
],
"oneOf": [
{
"type": "null"
},
{
"type": "array",
"items": {
"type": "string",
"enum": [
"insert-cell-below",
"move-cell-down",
"move-cell-up",
"run-cell-and-select-next"
]
},
"uniqueItems": true
}
]
},
"leftMenu": {
"title": "List of left menu items",
"description": "An item is defined by a 'command' name and an 'icon' name + optionally a 'tooltip' and the 'cellType' on which it applies",
Expand Down
27 changes: 4 additions & 23 deletions src/cellmenu.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ToolbarButton } from '@jupyterlab/apputils';
import { IObservableList } from '@jupyterlab/observables';
import { LabIcon } from '@jupyterlab/ui-components';
import { each } from '@lumino/algorithm';
import { CommandRegistry } from '@lumino/commands';
Expand All @@ -12,38 +11,21 @@ const CELL_MENU_CLASS = 'jp-enh-cell-menu';
* Toolbar icon menu container
*/
export class CellMenu extends Widget {
constructor(
commands: CommandRegistry,
items: IObservableList<ICellMenuItem>
) {
constructor(commands: CommandRegistry, items: ICellMenuItem[]) {
super();
this._commands = commands;
this._items = items;
this.layout = new PanelLayout();
this.addClass(CELL_MENU_CLASS);
this._itemsChanged(items);
this._items.changed.connect(this._itemsChanged, this);
this._addButtons(items);
}

dispose(): void {
if (this.isDisposed) {
return;
}
this._items.changed.disconnect(this._itemsChanged, this);

super.dispose();
}

protected _itemsChanged(
items: IObservableList<ICellMenuItem>,
changes?: IObservableList.IChangedArgs<ICellMenuItem>
): void {
protected _addButtons(items: ICellMenuItem[]): void {
each(this.children(), widget => {
widget.dispose();
});

const layout = this.layout as PanelLayout;
each(items.iter(), entry => {
items.forEach(entry => {
if (this._commands.hasCommand(entry.command)) {
layout.addWidget(
new ToolbarButton({
Expand All @@ -60,5 +42,4 @@ export class CellMenu extends Widget {
}

private _commands: CommandRegistry;
private _items: IObservableList<ICellMenuItem>;
}
74 changes: 29 additions & 45 deletions src/celltoolbartracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import {
markdownIcon,
runIcon
} from '@jupyterlab/ui-components';
import { each } from '@lumino/algorithm';
import { CommandRegistry } from '@lumino/commands';
import { IDisposable } from '@lumino/disposable';
import { PanelLayout, Widget } from '@lumino/widgets';
import { CellToolbarWidget, LEFT_SPACER_CLASSNAME } from './celltoolbarwidget';
import { CellToolbarWidget } from './celltoolbarwidget';
import { codeIcon, deleteIcon, formatIcon } from './icon';
import { PositionedButton } from './positionedbutton';
import { ICellMenuItem } from './tokens';
Expand Down Expand Up @@ -48,7 +49,7 @@ const DEFAULT_LEFT_MENU: ICellMenuItem[] = [
}
];

const POSITIONED_BUTTONS: ICellMenuItem[] = [
const DEFAULT_HELPER_BUTTONS: ICellMenuItem[] = [
// Originate from @jupyterlab/notebook-extension
{
command: 'notebook:run-cell-and-select-next',
Expand Down Expand Up @@ -112,6 +113,7 @@ export class CellToolbarTracker implements IDisposable {
const cells = this._panel?.context.model.cells;
if (cells) {
cells.changed.disconnect(this.updateConnectedCells, this);
each(cells.iter(), model => this._removeToolbar(model));
}
this._panel = null;
}
Expand All @@ -132,19 +134,34 @@ export class CellToolbarTracker implements IDisposable {

private _addToolbar(model: ICellModel): void {
const cell = this._getCell(model);

if (cell) {
let { helperButtons, leftMenu, rightMenu, leftSpace } = this._settings
?.composite as any;

helperButtons =
helperButtons === null
? []
: helperButtons ??
DEFAULT_HELPER_BUTTONS.map(entry => entry.command.split(':')[1]);
leftMenu = leftMenu === null ? [] : leftMenu ?? DEFAULT_LEFT_MENU;
rightMenu = rightMenu ?? [];
leftSpace = leftSpace ?? 0;

const toolbar = new CellToolbarWidget(
this._commands,
model,
this._allTags,
this._leftMenuItems,
this._rightMenuItems,
(this._settings?.composite['leftSpace'] as number) || 0
leftMenu,
rightMenu,
leftSpace
);
toolbar.addClass(CELL_BAR_CLASS);
(cell.layout as PanelLayout).insertWidget(0, toolbar);

POSITIONED_BUTTONS.forEach(entry => {
DEFAULT_HELPER_BUTTONS.filter(entry =>
(helperButtons as string[]).includes(entry.command.split(':')[1])
).forEach(entry => {
if (this._commands.hasCommand(entry.command)) {
const { cellType, command, tooltip, ...others } = entry;
const shortName = command.split(':')[1];
Expand Down Expand Up @@ -186,29 +203,12 @@ export class CellToolbarTracker implements IDisposable {
* Call back on settings changes
*/
private _onSettingsChanged(): void {
// Update menu items
const leftItems = (this._settings?.composite['leftMenu'] as any) as
| ICellMenuItem[]
| null;
// Test to avoid useless signal emission
if (this._leftMenuItems.length > 0) {
this._leftMenuItems.clear();
}
if (leftItems) {
if (leftItems.length > 0) {
this._leftMenuItems.pushAll(leftItems);
}
} else {
this._leftMenuItems.pushAll(DEFAULT_LEFT_MENU);
}
const rightItems = ((this._settings?.composite['rightMenu'] as any) ||
[]) as ICellMenuItem[];
// Test to avoid useless signal emission
if (this._rightMenuItems.length > 0) {
this._rightMenuItems.clear();
}
if (rightItems.length > 0) {
this._rightMenuItems.pushAll(rightItems);
// Reset toolbar when settings changes
if (this._panel?.context.model.cells) {
each(this._panel?.context.model.cells.iter(), model => {
this._removeToolbar(model);
this._addToolbar(model);
});
}

// Update tags
Expand All @@ -225,29 +225,13 @@ export class CellToolbarTracker implements IDisposable {
.filter(tag => !newDefaultTags.includes(tag))
.forEach(tag => this._allTags.removeValue(tag));
this._previousDefaultTags = newDefaultTags;

// Update left space
const leftSpace = (this._settings?.composite['leftSpace'] as number) || 0;
if (this._panel) {
this._panel.node
.querySelectorAll(`div.${LEFT_SPACER_CLASSNAME}`)
.forEach(node => {
(node as HTMLElement).style.width = `${leftSpace}px`;
});
}
}

private _allTags: ObservableList<string> = new ObservableList<string>();
private _commands: CommandRegistry;
private _isDisposed = false;
private _leftMenuItems: ObservableList<ICellMenuItem> = new ObservableList<
ICellMenuItem
>();
private _previousDefaultTags = new Array<string>();
private _panel: NotebookPanel | null;
private _rightMenuItems: ObservableList<ICellMenuItem> = new ObservableList<
ICellMenuItem
>();
private _settings: ISettingRegistry.ISettings | null;
}

Expand Down
4 changes: 2 additions & 2 deletions src/celltoolbarwidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export class CellToolbarWidget extends Widget {
commands: CommandRegistry,
model: ICellModel,
tagsList: ObservableList<string>,
leftMenuItems: ObservableList<ICellMenuItem>,
rightMenuItems: ObservableList<ICellMenuItem>,
leftMenuItems: ICellMenuItem[],
rightMenuItems: ICellMenuItem[],
leftSpace = 0
) {
super();
Expand Down

0 comments on commit fbe085a

Please sign in to comment.