forked from jupyter/jupyter-js-notebook
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNotebookWidget.ts
121 lines (102 loc) · 3.13 KB
/
NotebookWidget.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
'use strict';
import {
IChangedArgs
} from 'phosphor-properties';
import {
IObservableList, ObservableList, IListChangedArgs, ListChangeType
} from 'phosphor-observablelist';
import {
Widget, Panel
} from 'phosphor-widget';
import {
NotebookViewModel, INotebookViewModel
} from './NotebookViewModel';
import {
ICellViewModel, CellType,
CodeCellWidget, MarkdownCellWidget,
CodeCellViewModel, MarkdownCellViewModel
} from 'jupyter-js-cells';
import {
OutputAreaWidget, IOutputAreaViewModel
} from 'jupyter-js-output-area';
/**
* A widget for a notebook.
*/
export
class NotebookWidget extends Panel {
/**
* Construct a code cell widget.
*/
constructor(model: INotebookViewModel) {
super();
this.addClass('jp-Notebook');
this._model = model;
follow<ICellViewModel, Widget>(model.cells, this.children,
(c: ICellViewModel) => {
let w: Widget;
switch(c.type) {
case CellType.Code:
w = new CodeCellWidget(c as CodeCellViewModel);
break;
case CellType.Markdown:
w = new MarkdownCellWidget(c as MarkdownCellViewModel);
break;
default:
// if there are any issues, just return a blank placeholder
// widget so the lists stay in sync
w = new Widget();
}
return w;
})
model.stateChanged.connect(this.modelStateChanged, this);
model.cells.changed.connect(this.cellsChanged, this);
}
protected cellsChanged(sender: IObservableList<ICellViewModel>,
args: IListChangedArgs<ICellViewModel>) {
console.log(args);
}
/**
* Change handler for model updates.
*/
protected modelStateChanged(sender: INotebookViewModel, args: IChangedArgs<any>) {
switch(args.name) {
}
}
private _model: INotebookViewModel;
}
function follow<T,U>(source: IObservableList<T>,
sink: IObservableList<U>,
factory: (arg: T)=> U) {
// Hook up a listener to the source list
// make corresponding changes to the sink list
// invoke the add function when you need a new item for sink
// Initialize sink list
sink.clear();
for (let i=0; i<source.length; i++) {
sink.add(factory(source.get(i)))
}
source.changed.connect((sender, args) => {
switch(args.type) {
case ListChangeType.Add:
// TODO: type should probably be insert, not add, to be consistent with the functions
// TODO: Too bad we *always* have to cast newValue and oldValue
sink.insert(args.newIndex, factory(args.newValue as T))
break;
case ListChangeType.Move:
sink.move(args.oldIndex, args.newIndex);
break;
case ListChangeType.Remove:
sink.removeAt(args.oldIndex);
break;
case ListChangeType.Replace:
sink.replace(args.oldIndex, (args.oldValue as T[]).length,
(args.newValue as T[]).map(factory));
break;
case ListChangeType.Set:
sink.set(args.newIndex, factory(args.newValue as T))
break;
}
});
}