123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- // Copyright (c) Jupyter Development Team.
- // Distributed under the terms of the Modified BSD License.
- import {
- IIterator, find, map
- } from '@phosphor/algorithm';
- import {
- Message
- } from '@phosphor/messaging';
- import {
- AttachedProperty
- } from '@phosphor/properties';
- import {
- PanelLayout, Widget
- } from '@phosphor/widgets';
- import {
- IClientSession
- } from '.';
- /**
- * The class name added to toolbars.
- */
- const TOOLBAR_CLASS = 'jp-Toolbar';
- /**
- * The class name added to toolbar items.
- */
- const TOOLBAR_ITEM_CLASS = 'jp-Toolbar-item';
- /**
- * The class name added to toolbar buttons.
- */
- const TOOLBAR_BUTTON_CLASS = 'jp-Toolbar-button';
- /**
- * The class name added to a pressed button.
- */
- const TOOLBAR_PRESSED_CLASS = 'jp-mod-pressed';
- /**
- * The class name added to toolbar interrupt button.
- */
- const TOOLBAR_INTERRUPT_CLASS = 'jp-StopIcon';
- /**
- * The class name added to toolbar restart button.
- */
- const TOOLBAR_RESTART_CLASS = 'jp-RefreshIcon';
- /**
- * The class name added to toolbar kernel name text.
- */
- const TOOLBAR_KERNEL_CLASS = 'jp-Toolbar-kernelName';
- /**
- * The class name added to toolbar kernel indicator icon.
- */
- const TOOLBAR_INDICATOR_CLASS = 'jp-Toolbar-kernelIndicator';
- /**
- * The class name added to a busy kernel indicator.
- */
- const TOOLBAR_BUSY_CLASS = 'jp-mod-busy';
- /**
- * A class which provides a toolbar widget.
- */
- export
- class Toolbar<T extends Widget> extends Widget {
- /**
- * Construct a new toolbar widget.
- */
- constructor() {
- super();
- this.addClass(TOOLBAR_CLASS);
- this.layout = new PanelLayout();
- }
- /**
- * Get an iterator over the ordered toolbar item names.
- *
- * @returns An iterator over the toolbar item names.
- */
- names(): IIterator<string> {
- let layout = this.layout as PanelLayout;
- return map(layout.widgets, widget => {
- return Private.nameProperty.get(widget);
- });
- }
- /**
- * Add an item to the end of the toolbar.
- *
- * @param name - The name of the widget to add to the toolbar.
- *
- * @param widget - The widget to add to the toolbar.
- *
- * @param index - The optional name of the item to insert after.
- *
- * @returns Whether the item was added to toolbar. Returns false if
- * an item of the same name is already in the toolbar.
- */
- addItem(name: string, widget: T): boolean {
- let layout = this.layout as PanelLayout;
- return this.insertItem(layout.widgets.length, name, widget);
- }
- /**
- * Insert an item into the toolbar at the specified index.
- *
- * @param index - The index at which to insert the item.
- *
- * @param name - The name of the item.
- *
- * @param widget - The widget to add.
- *
- * @returns Whether the item was added to the toolbar. Returns false if
- * an item of the same name is already in the toolbar.
- *
- * #### Notes
- * The index will be clamped to the bounds of the items.
- */
- insertItem(index: number, name: string, widget: T): boolean {
- let existing = find(this.names(), value => value === name);
- if (existing) {
- return false;
- }
- widget.addClass(TOOLBAR_ITEM_CLASS);
- let layout = this.layout as PanelLayout;
- layout.insertWidget(index, widget);
- Private.nameProperty.set(widget, name);
- return true;
- }
- /**
- * Remove an item in the toolbar by value.
- *
- * @param name - The name of the widget to remove from the toolbar.
- */
- removeItem(widget: T): void {
- let layout = this.layout as PanelLayout;
- layout.removeWidget(widget);
- }
- /**
- * Handle the DOM events for the widget.
- *
- * @param event - The DOM event sent to the widget.
- *
- * #### Notes
- * This method implements the DOM `EventListener` interface and is
- * called in response to events on the dock panel's node. It should
- * not be called directly by user code.
- */
- handleEvent(event: Event): void {
- switch (event.type) {
- case 'click':
- if (!this.node.contains(document.activeElement)) {
- this.parent.activate();
- }
- break;
- default:
- break;
- }
- }
- /**
- * Handle `after-attach` messages for the widget.
- */
- protected onAfterAttach(msg: Message): void {
- this.node.addEventListener('click', this);
- }
- /**
- * Handle `before-detach` messages for the widget.
- */
- protected onBeforeDetach(msg: Message): void {
- this.node.removeEventListener('click', this);
- }
- }
- /**
- * The namespace for Toolbar class statics.
- */
- export
- namespace Toolbar {
- /**
- * Create an interrupt toolbar item.
- */
- export
- function createInterruptButton(session: IClientSession): ToolbarButton {
- return new ToolbarButton({
- className: TOOLBAR_INTERRUPT_CLASS,
- onClick: () => {
- if (session.kernel) {
- session.kernel.interrupt();
- }
- },
- tooltip: 'Interrupt the kernel'
- });
- }
- /**
- * Create a restart toolbar item.
- */
- export
- function createRestartButton(session: IClientSession): ToolbarButton {
- return new ToolbarButton({
- className: TOOLBAR_RESTART_CLASS,
- onClick: () => {
- session.restart();
- },
- tooltip: 'Restart the kernel'
- });
- }
- /**
- * Create a kernel name indicator item.
- *
- * #### Notes
- * It will display the `'display_name`' of the current kernel,
- * or `'No Kernel!'` if there is no kernel.
- * It can handle a change in context or kernel.
- */
- export
- function createKernelNameItem(session: IClientSession): Widget {
- return new Private.KernelName(session);
- }
- /**
- * Create a kernel status indicator item.
- *
- * #### Notes
- * It show display a busy status if the kernel status is
- * not idle.
- * It will show the current status in the node title.
- * It can handle a change to the context or the kernel.
- */
- export
- function createKernelStatusItem(session: IClientSession): Widget {
- return new Private.KernelIndicator(session);
- }
- }
- /**
- * A widget which acts as a button in a toolbar.
- */
- export
- class ToolbarButton extends Widget {
- /**
- * Construct a new toolbar button.
- */
- constructor(options: ToolbarButton.IOptions = {}) {
- super({ node: document.createElement('span') });
- options = options || {};
- this.addClass(TOOLBAR_BUTTON_CLASS);
- this._onClick = options.onClick;
- if (options.className) {
- this.addClass(options.className);
- }
- this.node.title = options.tooltip || '';
- }
- /**
- * Dispose of the resources held by the widget.
- */
- dispose(): void {
- this._onClick = null;
- super.dispose();
- }
- /**
- * Handle the DOM events for the widget.
- *
- * @param event - The DOM event sent to the widget.
- *
- * #### Notes
- * This method implements the DOM `EventListener` interface and is
- * called in response to events on the dock panel's node. It should
- * not be called directly by user code.
- */
- handleEvent(event: Event): void {
- switch (event.type) {
- case 'click':
- if (this._onClick) {
- this._onClick();
- }
- break;
- case 'mousedown':
- this.addClass(TOOLBAR_PRESSED_CLASS);
- break;
- case 'mouseup':
- case 'mouseout':
- this.removeClass(TOOLBAR_PRESSED_CLASS);
- break;
- default:
- break;
- }
- }
- /**
- * Handle `after-attach` messages for the widget.
- */
- protected onAfterAttach(msg: Message): void {
- this.node.addEventListener('click', this);
- this.node.addEventListener('mousedown', this);
- this.node.addEventListener('mouseup', this);
- this.node.addEventListener('mouseout', this);
- }
- /**
- * Handle `before-detach` messages for the widget.
- */
- protected onBeforeDetach(msg: Message): void {
- this.node.removeEventListener('click', this);
- this.node.removeEventListener('mousedown', this);
- this.node.removeEventListener('mouseup', this);
- this.node.removeEventListener('mouseout', this);
- }
- private _onClick: () => void;
- }
- /**
- * A namespace for `ToolbarButton` statics.
- */
- export
- namespace ToolbarButton {
- /**
- * The options used to construct a toolbar button.
- */
- export
- interface IOptions {
- /**
- * The callback for a click event.
- */
- onClick?: () => void;
- /**
- * The class name added to the button.
- */
- className?: string;
- /**
- * The tooltip added to the button node.
- */
- tooltip?: string;
- }
- }
- /**
- * A namespace for private data.
- */
- namespace Private {
- /**
- * An attached property for the name of a toolbar item.
- */
- export
- const nameProperty = new AttachedProperty<Widget, string>({
- name: 'name',
- create: () => ''
- });
- /**
- * A kernel name widget.
- */
- export
- class KernelName extends Widget {
- /**
- * Construct a new kernel name widget.
- */
- constructor(session: IClientSession) {
- super();
- this.addClass(TOOLBAR_KERNEL_CLASS);
- this._onKernelChanged(session);
- session.kernelChanged.connect(this._onKernelChanged, this);
- }
- /**
- * Update the text of the kernel name item.
- */
- _onKernelChanged(session: IClientSession): void {
- this.node.textContent = session.kernelDisplayName;
- }
- }
- /**
- * A toolbar item that displays kernel status.
- */
- export
- class KernelIndicator extends Widget {
- /**
- * Construct a new kernel status widget.
- */
- constructor(session: IClientSession) {
- super();
- this.addClass(TOOLBAR_INDICATOR_CLASS);
- this._onStatusChanged(session);
- session.statusChanged.connect(this._onStatusChanged, this);
- }
- /**
- * Handle a status on a kernel.
- */
- private _onStatusChanged(session: IClientSession) {
- if (this.isDisposed) {
- return;
- }
- let status = session.status;
- this.toggleClass(TOOLBAR_BUSY_CLASS, status !== 'idle');
- let title = 'Kernel ' + status[0].toUpperCase() + status.slice(1);
- this.node.title = title;
- }
- }
- }
|