123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- // Copyright (c) Jupyter Development Team.
- // Distributed under the terms of the Modified BSD License.
- import { ISettingRegistry } from '@jupyterlab/settingregistry';
- import { INotebookTracker } from '@jupyterlab/notebook';
- import { IMainMenu, } from '@jupyterlab/mainmenu';
- import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
- import { ILoggerRegistry } from '@jupyterlab/logconsole';
- import { toArray, filter } from '@lumino/algorithm';
- import { DisposableDelegate } from '@lumino/disposable';
- import { AttachedProperty } from '@lumino/properties';
- import { WidgetRenderer } from './renderer';
- import { WidgetManager, WIDGET_VIEW_MIMETYPE } from './manager';
- import { OutputModel, OutputView, OUTPUT_WIDGET_VERSION } from './output';
- import * as base from '@jupyter-widgets/base';
- // We import only the version from the specific module in controls so that the
- // controls code can be split and dynamically loaded in webpack.
- import { JUPYTER_CONTROLS_VERSION } from '@jupyter-widgets/controls/lib/version';
- import '@jupyter-widgets/base/css/index.css';
- import '@jupyter-widgets/controls/css/widgets-base.css';
- import { KernelMessage } from '@jupyterlab/services';
- const WIDGET_REGISTRY = [];
- /**
- * The cached settings.
- */
- const SETTINGS = { saveState: false };
- /**
- * Iterate through all widget renderers in a notebook.
- */
- function* widgetRenderers(nb) {
- for (let cell of nb.widgets) {
- if (cell.model.type === 'code') {
- for (let codecell of cell.outputArea.widgets) {
- for (let output of toArray(codecell.children())) {
- if (output instanceof WidgetRenderer) {
- yield output;
- }
- }
- }
- }
- }
- }
- /**
- * Iterate through all matching linked output views
- */
- function* outputViews(app, path) {
- let linkedViews = filter(app.shell.widgets(), w => w.id.startsWith('LinkedOutputView-') && w.path === path);
- for (let view of toArray(linkedViews)) {
- for (let outputs of toArray(view.children())) {
- for (let output of toArray(outputs.children())) {
- if (output instanceof WidgetRenderer) {
- yield output;
- }
- }
- }
- }
- }
- function* chain(...args) {
- for (let it of args) {
- yield* it;
- }
- }
- export function registerWidgetManager(context, rendermime, renderers) {
- let wManager = Private.widgetManagerProperty.get(context);
- if (!wManager) {
- wManager = new WidgetManager(context, rendermime, SETTINGS);
- WIDGET_REGISTRY.forEach(data => wManager.register(data));
- Private.widgetManagerProperty.set(context, wManager);
- }
- for (let r of renderers) {
- r.manager = wManager;
- }
- // Replace the placeholder widget renderer with one bound to this widget
- // manager.
- rendermime.removeMimeType(WIDGET_VIEW_MIMETYPE);
- rendermime.addFactory({
- safe: false,
- mimeTypes: [WIDGET_VIEW_MIMETYPE],
- createRenderer: (options) => new WidgetRenderer(options, wManager)
- }, 0);
- return new DisposableDelegate(() => {
- if (rendermime) {
- rendermime.removeMimeType(WIDGET_VIEW_MIMETYPE);
- }
- wManager.dispose();
- });
- }
- /**
- * The widget manager provider.
- */
- const plugin = {
- id: '@jupyter-widgets/jupyterlab-manager:plugin',
- requires: [IRenderMimeRegistry, ISettingRegistry],
- optional: [INotebookTracker, IMainMenu, ILoggerRegistry],
- provides: base.IJupyterWidgetRegistry,
- activate: activateWidgetExtension,
- autoStart: true
- };
- export default plugin;
- function updateSettings(settings) {
- SETTINGS.saveState = settings.get('saveState').composite;
- }
- /**
- * Activate the widget extension.
- */
- function activateWidgetExtension(app, rendermime, settingRegistry, tracker, menu, loggerRegistry) {
- const { commands } = app;
- const bindUnhandledIOPubMessageSignal = (nb) => {
- if (!loggerRegistry) {
- return;
- }
- const wManager = Private.widgetManagerProperty.get(nb.context);
- if (wManager) {
- wManager.onUnhandledIOPubMessage.connect((sender, msg) => {
- const logger = loggerRegistry.getLogger(nb.context.path);
- let level = 'warning';
- if (KernelMessage.isErrorMsg(msg) ||
- (KernelMessage.isStreamMsg(msg) && msg.content.name === 'stderr')) {
- level = 'error';
- }
- const data = Object.assign(Object.assign({}, msg.content), { output_type: msg.header.msg_type });
- logger.rendermime = nb.content.rendermime;
- logger.log({ type: 'output', data, level });
- });
- }
- };
- settingRegistry.load(plugin.id).then((settings) => {
- settings.changed.connect(updateSettings);
- updateSettings(settings);
- }).catch((reason) => {
- console.error(reason.message);
- });
- // Add a placeholder widget renderer.
- rendermime.addFactory({
- safe: false,
- mimeTypes: [WIDGET_VIEW_MIMETYPE],
- createRenderer: options => new WidgetRenderer(options)
- }, 0);
- if (tracker) {
- tracker.forEach(panel => {
- registerWidgetManager(panel.context, panel.content.rendermime, chain(widgetRenderers(panel.content), outputViews(app, panel.context.path)));
- bindUnhandledIOPubMessageSignal(panel);
- });
- tracker.widgetAdded.connect((sender, panel) => {
- registerWidgetManager(panel.context, panel.content.rendermime, chain(widgetRenderers(panel.content), outputViews(app, panel.context.path)));
- bindUnhandledIOPubMessageSignal(panel);
- });
- }
- // Add a command for creating a new Markdown file.
- commands.addCommand('@jupyter-widgets/jupyterlab-manager:saveWidgetState', {
- label: 'Save Widget State Automatically',
- execute: args => {
- return settingRegistry
- .set(plugin.id, 'saveState', !SETTINGS.saveState)
- .catch((reason) => {
- console.error(`Failed to set ${plugin.id}: ${reason.message}`);
- });
- },
- isToggled: () => SETTINGS.saveState
- });
- if (menu) {
- menu.settingsMenu.addGroup([
- { command: '@jupyter-widgets/jupyterlab-manager:saveWidgetState' }
- ]);
- }
- WIDGET_REGISTRY.push({
- name: '@jupyter-widgets/base',
- version: base.JUPYTER_WIDGETS_VERSION,
- exports: {
- WidgetModel: base.WidgetModel,
- WidgetView: base.WidgetView,
- DOMWidgetView: base.DOMWidgetView,
- DOMWidgetModel: base.DOMWidgetModel,
- LayoutModel: base.LayoutModel,
- LayoutView: base.LayoutView,
- StyleModel: base.StyleModel,
- StyleView: base.StyleView
- }
- });
- WIDGET_REGISTRY.push({
- name: '@jupyter-widgets/controls',
- version: JUPYTER_CONTROLS_VERSION,
- exports: () => {
- return new Promise((resolve, reject) => {
- require.ensure(['@jupyter-widgets/controls'], (require) => {
- resolve(require('@jupyter-widgets/controls'));
- }, (err) => {
- reject(err);
- }, '@jupyter-widgets/controls');
- });
- }
- });
- WIDGET_REGISTRY.push({
- name: '@jupyter-widgets/output',
- version: OUTPUT_WIDGET_VERSION,
- exports: { OutputModel, OutputView }
- });
- return {
- registerWidget(data) {
- WIDGET_REGISTRY.push(data);
- }
- };
- }
- var Private;
- (function (Private) {
- /**
- * A private attached property for a widget manager.
- */
- Private.widgetManagerProperty = new AttachedProperty({
- name: 'widgetManager',
- create: () => undefined
- });
- })(Private || (Private = {}));
|