sophon-notebook-notebook
Version:
JupyterLab - Notebook
212 lines • 7.17 kB
JavaScript
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
import { Token } from '@phosphor/coreutils';
import { Signal } from '@phosphor/signaling';
import { Printing, showDialog, Dialog } from 'sophon-notebook-apputils';
import { DocumentWidget } from 'sophon-notebook-docregistry';
import { Notebook } from './widget';
import { PageConfig } from 'sophon-notebook-coreutils';
/**
* The class name added to notebook panels.
*/
const NOTEBOOK_PANEL_CLASS = 'jp-NotebookPanel';
const NOTEBOOK_PANEL_TOOLBAR_CLASS = 'jp-NotebookPanel-toolbar';
const NOTEBOOK_PANEL_NOTEBOOK_CLASS = 'jp-NotebookPanel-notebook';
/**
* A widget that hosts a notebook toolbar and content area.
*
* #### Notes
* The widget keeps the document metadata in sync with the current
* kernel on the context.
*/
export class NotebookPanel extends DocumentWidget {
/**
* Construct a new notebook panel.
*/
constructor(options) {
super(options);
this._activated = new Signal(this);
/**
* Whether we are currently in a series of autorestarts we have already
* notified the user about.
*/
this._autorestarting = false;
// Set up CSS classes
this.addClass(NOTEBOOK_PANEL_CLASS);
this.toolbar.addClass(NOTEBOOK_PANEL_TOOLBAR_CLASS);
this.content.addClass(NOTEBOOK_PANEL_NOTEBOOK_CLASS);
// Set up things related to the context
this.content.model = this.context.model;
this.context.session.kernelChanged.connect(this._onKernelChanged, this);
this.context.session.statusChanged.connect(this._onSessionStatusChanged, this);
void this.revealed.then(() => {
if (this.isDisposed) {
// this widget has already been disposed, bail
return;
}
// Set the document edit mode on initial open if it looks like a new document.
if (this.content.widgets.length === 1) {
let cellModel = this.content.widgets[0].model;
if (cellModel.type === 'code' && cellModel.value.text === '') {
this.content.mode = 'edit';
}
}
});
}
/**
* A signal emitted when the panel has been activated.
*/
get activated() {
return this._activated;
}
/**
* The client session used by the panel.
*/
get session() {
return this.context.session;
}
/**
* The model for the widget.
*/
get model() {
return this.content ? this.content.model : null;
}
/**
* Update the options for the current notebook panel.
*
* @param config new options to set
*/
setConfig(config) {
this.content.editorConfig = config.editorConfig;
this.content.notebookConfig = config.notebookConfig;
// Update kernel shutdown behavior
const kernelPreference = this.context.session.kernelPreference;
this.context.session.kernelPreference = Object.assign({}, kernelPreference, { shutdownOnClose: config.kernelShutdown });
}
/**
* Set URI fragment identifier.
*/
setFragment(fragment) {
void this.context.ready.then(() => {
this.content.setFragment(fragment);
});
}
/**
* Dispose of the resources used by the widget.
*/
dispose() {
this.content.dispose();
super.dispose();
}
/**
* Handle `'activate-request'` messages.
*/
onActivateRequest(msg) {
super.onActivateRequest(msg);
// TODO: do we still need to emit this signal? Who is using it?
this._activated.emit(void 0);
}
/**
* Prints the notebook by converting to HTML with nbconvert.
*/
[Printing.symbol]() {
return async () => {
// Save before generating HTML
if (this.context.model.dirty && !this.context.model.readOnly) {
await this.context.save();
}
await Printing.printURL(PageConfig.getNBConvertURL({
format: 'html',
download: false,
path: this.context.path
}));
};
}
/**
* Handle a change in the kernel by updating the document metadata.
*/
_onKernelChanged(sender, args) {
if (!this.model || !args.newValue) {
return;
}
let { newValue } = args;
void newValue.ready.then(() => {
if (this.model && this.context.session.kernel === newValue) {
this._updateLanguage(newValue.info.language_info);
}
});
void this._updateSpec(newValue);
}
_onSessionStatusChanged(sender, status) {
// If the status is autorestarting, and we aren't already in a series of
// autorestarts, show the dialog.
if (status === 'autorestarting' && !this._autorestarting) {
// The kernel died and the server is restarting it. We notify the user so
// they know why their kernel state is gone.
void showDialog({
title: 'Kernel Restarting',
body: `The kernel for ${this.session.path} appears to have died. It will restart automatically.`,
buttons: [Dialog.okButton()]
});
this._autorestarting = true;
}
else if (status === 'restarting') {
// Another autorestart attempt will first change the status to
// restarting, then to autorestarting again, so we don't reset the
// autorestarting status if the status is 'restarting'.
/* no-op */
}
else {
this._autorestarting = false;
}
}
/**
* Update the kernel language.
*/
_updateLanguage(language) {
this.model.metadata.set('language_info', language);
}
/**
* Update the kernel spec.
*/
_updateSpec(kernel) {
return kernel.getSpec().then(spec => {
if (this.isDisposed) {
return;
}
this.model.metadata.set('kernelspec', {
name: kernel.name,
display_name: spec.display_name,
language: spec.language
});
});
}
}
/**
* A namespace for `NotebookPanel` statics.
*/
(function (NotebookPanel) {
/**
* The default implementation of an `IContentFactory`.
*/
class ContentFactory extends Notebook.ContentFactory {
/**
* Create a new content area for the panel.
*/
createNotebook(options) {
return new Notebook(options);
}
}
NotebookPanel.ContentFactory = ContentFactory;
/**
* Default content factory for the notebook panel.
*/
NotebookPanel.defaultContentFactory = new ContentFactory();
/* tslint:disable */
/**
* The notebook renderer token.
*/
NotebookPanel.IContentFactory = new Token('sophon-notebook-notebook:IContentFactory');
/* tslint:enable */
})(NotebookPanel || (NotebookPanel = {}));
//# sourceMappingURL=panel.js.map