@jupyter-widgets/jupyterlab-manager
Version:
The JupyterLab extension providing Jupyter widgets.
130 lines • 4.71 kB
JavaScript
// 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