@jupyterlab/notebook
Version:
JupyterLab - Notebook
139 lines • 4.45 kB
JavaScript
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
import { CodeCellModel, MarkdownCellModel, RawCellModel } from '@jupyterlab/cells';
import { Signal } from '@lumino/signaling';
/**
* A cell list object that supports undo/redo.
*/
export class CellList {
/**
* Construct the cell list.
*/
constructor(model) {
this.model = model;
this._cellMap = new WeakMap();
this._changed = new Signal(this);
this._isDisposed = false;
this._insertCells(0, this.model.cells);
this.model.changed.connect(this._onSharedModelChanged, this);
}
/**
* A signal emitted when the cell list has changed.
*/
get changed() {
return this._changed;
}
/**
* Test whether the cell list has been disposed.
*/
get isDisposed() {
return this._isDisposed;
}
/**
* Get the length of the cell list.
*
* @returns The number of cells in the cell list.
*/
get length() {
return this.model.cells.length;
}
/**
* Create an iterator over the cells in the cell list.
*
* @returns A new iterator starting at the front of the cell list.
*/
*[Symbol.iterator]() {
for (const cell of this.model.cells) {
yield this._cellMap.get(cell);
}
}
/**
* Dispose of the resources held by the cell list.
*/
dispose() {
var _a;
if (this._isDisposed) {
return;
}
this._isDisposed = true;
// Clean up the cell map and cell order objects.
for (const cell of this.model.cells) {
(_a = this._cellMap.get(cell)) === null || _a === void 0 ? void 0 : _a.dispose();
}
Signal.clearData(this);
}
/**
* Get the cell at the specified index.
*
* @param index - The positive integer index of interest.
*
* @returns The cell at the specified index.
*/
get(index) {
return this._cellMap.get(this.model.cells[index]);
}
_insertCells(index, cells) {
cells.forEach(sharedModel => {
let cellModel;
switch (sharedModel.cell_type) {
case 'code': {
cellModel = new CodeCellModel({
sharedModel: sharedModel
});
break;
}
case 'markdown': {
cellModel = new MarkdownCellModel({
sharedModel: sharedModel
});
break;
}
default: {
cellModel = new RawCellModel({
sharedModel: sharedModel
});
}
}
this._cellMap.set(sharedModel, cellModel);
sharedModel.disposed.connect(() => {
cellModel.dispose();
this._cellMap.delete(sharedModel);
});
});
return this.length;
}
_onSharedModelChanged(self, change) {
var _a;
let currpos = 0;
// We differ emitting the list changes to ensure cell model for all current shared cell have been created.
const events = new Array();
(_a = change.cellsChange) === null || _a === void 0 ? void 0 : _a.forEach(delta => {
if (delta.insert != null) {
this._insertCells(currpos, delta.insert);
events.push({
type: 'add',
newIndex: currpos,
newValues: delta.insert.map(c => this._cellMap.get(c)),
oldIndex: -2,
oldValues: []
});
currpos += delta.insert.length;
}
else if (delta.delete != null) {
events.push({
type: 'remove',
newIndex: -1,
newValues: [],
oldIndex: currpos,
// Cells have been disposed, so we don't know which one are gone.
oldValues: new Array(delta.delete).fill(undefined)
});
}
else if (delta.retain != null) {
currpos += delta.retain;
}
});
events.forEach(msg => this._changed.emit(msg));
}
}
//# sourceMappingURL=celllist.js.map