|
@@ -7,7 +7,7 @@ import {
|
|
|
} from 'jupyter-js-docmanager';
|
|
|
|
|
|
import {
|
|
|
- NotebookWidget, NotebookModel, NBData, populateNotebookModel, buildOutputModel, Output, INotebookModel
|
|
|
+ NotebookWidget, NotebookModel, populateNotebookModel, buildOutputModel, Output, INotebookModel, getNotebookContent
|
|
|
} from 'jupyter-js-notebook';
|
|
|
|
|
|
import {
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
} from 'jupyter-js-notebook/lib/cells';
|
|
|
|
|
|
import {
|
|
|
- IContentsModel, IContentsManager,
|
|
|
+ IContentsModel, IContentsManager, IContentsOpts,
|
|
|
NotebookSessionManager, INotebookSessionManager,
|
|
|
INotebookSession, IKernelMessage, IComm
|
|
|
} from 'jupyter-js-services';
|
|
@@ -52,12 +52,6 @@ let selectPreviousCellCommandId = 'notebook:select-previous-cell';
|
|
|
let notebookContainerClass = 'jp-NotebookContainer';
|
|
|
|
|
|
|
|
|
-/**
|
|
|
- * The class name added to a dirty documents.
|
|
|
- */
|
|
|
-const DIRTY_CLASS = 'jp-mod-dirty';
|
|
|
-
|
|
|
-
|
|
|
/**
|
|
|
* The notebook file handler provider.
|
|
|
*/
|
|
@@ -119,7 +113,6 @@ class NotebookContainer extends Panel {
|
|
|
constructor() {
|
|
|
super();
|
|
|
this._model = new NotebookModel();
|
|
|
- this._model.stateChanged.connect(this._onModelChanged, this);
|
|
|
let widgetarea = new Widget();
|
|
|
this._manager = new WidgetManager(widgetarea.node);
|
|
|
let widget = new NotebookWidget(this._model);
|
|
@@ -174,16 +167,6 @@ class NotebookContainer extends Panel {
|
|
|
this._session.kernel.registerCommTarget('jupyter.widget', commHandler);
|
|
|
}
|
|
|
|
|
|
- private _onModelChanged(model: INotebookModel, args: IChangedArgs<INotebookModel>): void {
|
|
|
- if (args.name === 'dirty') {
|
|
|
- if (args.newValue) {
|
|
|
- this.addClass(DIRTY_CLASS);
|
|
|
- } else {
|
|
|
- this.removeClass(DIRTY_CLASS);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
private _model: INotebookModel = null;
|
|
|
private _session: INotebookSession = null;
|
|
|
private _manager: WidgetManager = null;
|
|
@@ -193,8 +176,7 @@ class NotebookContainer extends Panel {
|
|
|
/**
|
|
|
* An implementation of a file handler.
|
|
|
*/
|
|
|
-export
|
|
|
-class NotebookFileHandler extends AbstractFileHandler {
|
|
|
+class NotebookFileHandler extends AbstractFileHandler<NotebookContainer> {
|
|
|
|
|
|
constructor(contents: IContentsManager, session: INotebookSessionManager) {
|
|
|
super(contents);
|
|
@@ -212,7 +194,7 @@ class NotebookFileHandler extends AbstractFileHandler {
|
|
|
* Run the selected cell on the active widget.
|
|
|
*/
|
|
|
runSelectedCell(): void {
|
|
|
- let w = this.activeWidget as NotebookContainer;
|
|
|
+ let w = this.activeWidget;
|
|
|
if (w) w.model.runSelectedCell();
|
|
|
}
|
|
|
|
|
@@ -220,7 +202,7 @@ class NotebookFileHandler extends AbstractFileHandler {
|
|
|
* Select the next cell on the active widget.
|
|
|
*/
|
|
|
selectNextCell(): void {
|
|
|
- let w = this.activeWidget as NotebookContainer;
|
|
|
+ let w = this.activeWidget;
|
|
|
if (w) w.model.selectNextCell();
|
|
|
}
|
|
|
|
|
@@ -228,28 +210,59 @@ class NotebookFileHandler extends AbstractFileHandler {
|
|
|
* Select the previous cell on the active widget.
|
|
|
*/
|
|
|
selectPreviousCell(): void {
|
|
|
- let w = this.activeWidget as NotebookContainer;
|
|
|
+ let w = this.activeWidget;
|
|
|
if (w) w.model.selectPreviousCell();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Get file contents given a contents model.
|
|
|
+ * Set the dirty state of a widget (defaults to current active widget).
|
|
|
*/
|
|
|
- protected getContents(model: IContentsModel): Promise<IContentsModel> {
|
|
|
- return this.manager.get(model.path, { type: 'notebook' });
|
|
|
+ setDirty(widget?: NotebookContainer): void {
|
|
|
+ super.setDirty(widget);
|
|
|
+ widget = this.resolveWidget(widget);
|
|
|
+ if (widget) {
|
|
|
+ widget.model.dirty = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Clear the dirty state of a widget (defaults to current active widget).
|
|
|
+ */
|
|
|
+ clearDirty(widget?: NotebookContainer): void {
|
|
|
+ super.clearDirty(widget);
|
|
|
+ widget = this.resolveWidget(widget);
|
|
|
+ if (widget) {
|
|
|
+ widget.model.dirty = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get options use to fetch the model contents from disk.
|
|
|
+ */
|
|
|
+ protected getFetchOptions(model: IContentsModel): IContentsOpts {
|
|
|
+ return { type: 'notebook' };
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get the options used to save the widget content.
|
|
|
+ */
|
|
|
+ protected getSaveOptions(widget: NotebookContainer, model: IContentsModel): Promise<IContentsOpts> {
|
|
|
+ let content = getNotebookContent(widget.model);
|
|
|
+ return Promise.resolve({ type: 'notebook', content });
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Create the widget from an `IContentsModel`.
|
|
|
*/
|
|
|
- protected createWidget(contents: IContentsModel): Widget {
|
|
|
+ protected createWidget(contents: IContentsModel): NotebookContainer {
|
|
|
let panel = new NotebookContainer();
|
|
|
+ panel.model.stateChanged.connect(this._onModelChanged, this);
|
|
|
panel.title.text = contents.name;
|
|
|
panel.addClass(notebookContainerClass);
|
|
|
|
|
|
this.session.startNew({notebookPath: contents.path}).then(s => {
|
|
|
panel.setSession(s);
|
|
|
- })
|
|
|
+ });
|
|
|
|
|
|
return panel;
|
|
|
}
|
|
@@ -257,28 +270,35 @@ class NotebookFileHandler extends AbstractFileHandler {
|
|
|
/**
|
|
|
* Populate the notebook widget with the contents of the notebook.
|
|
|
*/
|
|
|
- protected setState(widget: Widget, model: IContentsModel): Promise<void> {
|
|
|
- let nbData: NBData = {
|
|
|
- content: model.content,
|
|
|
- name: model.name,
|
|
|
- path: model.path
|
|
|
+ protected populateWidget(widget: NotebookContainer, model: IContentsModel): Promise<IContentsModel> {
|
|
|
+ populateNotebookModel(widget.model, model.content);
|
|
|
+ if (widget.model.cells.length === 0) {
|
|
|
+ let cell = widget.model.createCodeCell();
|
|
|
+ widget.model.cells.add(cell);
|
|
|
}
|
|
|
- let nbWidget: NotebookWidget = ((widget as Panel).childAt(1)) as NotebookWidget;
|
|
|
- populateNotebookModel(nbWidget.model, nbData);
|
|
|
- if (nbWidget.model.cells.length === 0) {
|
|
|
- let cell = nbWidget.model.createCodeCell();
|
|
|
- nbWidget.model.cells.add(cell);
|
|
|
- }
|
|
|
- nbWidget.model.selectedCellIndex = 0;
|
|
|
+ widget.model.selectedCellIndex = 0;
|
|
|
|
|
|
- return Promise.resolve();
|
|
|
+ return Promise.resolve(model);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Get the current state of the notebook.
|
|
|
+ * Handle changes to the model state of a widget.
|
|
|
*/
|
|
|
- protected getState(widget: Widget, model: IContentsModel): Promise<IContentsModel> {
|
|
|
- return Promise.resolve(void 0);
|
|
|
+ private _onModelChanged(model: INotebookModel, args: IChangedArgs<INotebookModel>): void {
|
|
|
+ if (args.name !== 'dirty') {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for (let i = 0; i < this.widgetCount(); i++) {
|
|
|
+ let widget = this.widgetAt(i);
|
|
|
+ if (widget.model === model) {
|
|
|
+ if (args.newValue) {
|
|
|
+ this.setDirty(widget);
|
|
|
+ } else {
|
|
|
+ this.clearDirty(widget);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
session: INotebookSessionManager;
|