UNPKG

@jupyter-widgets/jupyterlab-manager

Version:

The JupyterLab extension providing Jupyter widgets.

130 lines 4.71 kB
// Copyright (c) Jupyter Development Team. // Distributed under the terms of the Modified BSD License. import * as outputBase from '@jupyter-widgets/output'; import { JupyterLuminoPanelWidget } from '@jupyter-widgets/base'; import { WidgetManager } from './manager'; import { OutputAreaModel, OutputArea } from '@jupyterlab/outputarea'; import $ from 'jquery'; export const OUTPUT_WIDGET_VERSION = outputBase.OUTPUT_WIDGET_VERSION; export class OutputModel extends outputBase.OutputModel { defaults() { return Object.assign(Object.assign({}, super.defaults()), { msg_id: '', outputs: [] }); } initialize(attributes, options) { super.initialize(attributes, options); // The output area model is trusted since widgets are only rendered in trusted contexts. this._outputs = new OutputAreaModel({ trusted: true }); this._msgHook = (msg) => { this.add(msg); return false; }; // if the context is available, react on kernel changes if (this.widget_manager instanceof WidgetManager) { this.widget_manager.context.sessionContext.kernelChanged.connect((sender, args) => { this._handleKernelChanged(args); }); } this.listenTo(this, 'change:msg_id', this.reset_msg_id); this.listenTo(this, 'change:outputs', this.setOutputs); this.setOutputs(); } /** * Register a new kernel */ _handleKernelChanged({ oldValue, }) { const msgId = this.get('msg_id'); if (msgId && oldValue) { oldValue.removeMessageHook(msgId, this._msgHook); this.set('msg_id', null); } } /** * Reset the message id. */ reset_msg_id() { const kernel = this.widget_manager.kernel; const msgId = this.get('msg_id'); const oldMsgId = this.previous('msg_id'); // Clear any old handler. if (oldMsgId && kernel) { kernel.removeMessageHook(oldMsgId, this._msgHook); } // Register any new handler. if (msgId && kernel) { kernel.registerMessageHook(msgId, this._msgHook); } } add(msg) { const msgType = msg.header.msg_type; switch (msgType) { case 'execute_result': case 'display_data': case 'stream': case 'error': { const model = msg.content; model.output_type = msgType; this._outputs.add(model); break; } case 'clear_output': this.clear_output(msg.content.wait); break; default: break; } this.set('outputs', this._outputs.toJSON(), { newMessage: true }); this.save_changes(); } clear_output(wait = false) { this._outputs.clear(wait); } get outputs() { return this._outputs; } setOutputs(model, value, options) { if (!(options && options.newMessage)) { // fromJSON does not clear the existing output this.clear_output(); // fromJSON does not copy the message, so we make a deep copy this._outputs.fromJSON(JSON.parse(JSON.stringify(this.get('outputs')))); } } } export class OutputView extends outputBase.OutputView { _createElement(tagName) { this.luminoWidget = new JupyterLuminoPanelWidget({ view: this }); return this.luminoWidget.node; } _setElement(el) { if (this.el || el !== this.luminoWidget.node) { // Boxes don't allow setting the element beyond the initial creation. throw new Error('Cannot reset the DOM element.'); } this.el = this.luminoWidget.node; this.$el = $(this.luminoWidget.node); } /** * Called when view is rendered. */ render() { super.render(); this._outputView = new OutputArea({ rendermime: this.model.widget_manager.rendermime, contentFactory: OutputArea.defaultContentFactory, model: this.model.outputs, }); // TODO: why is this a readonly property now? // this._outputView.model = this.model.outputs; // TODO: why is this on the model now? // this._outputView.trusted = true; this.luminoWidget.insertWidget(0, this._outputView); this.luminoWidget.addClass('jupyter-widgets'); this.luminoWidget.addClass('widget-output'); this.update(); // Set defaults. } remove() { this._outputView.dispose(); return super.remove(); } } //# sourceMappingURL=output.js.map