-
Notifications
You must be signed in to change notification settings - Fork 945
/
renderer.ts
130 lines (109 loc) · 3.44 KB
/
renderer.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
122
123
124
125
126
127
128
129
130
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
import { PromiseDelegate } from '@lumino/coreutils';
import { IDisposable } from '@lumino/disposable';
import { Panel, Widget as LuminoWidget } from '@lumino/widgets';
import { IRenderMime } from '@jupyterlab/rendermime-interfaces';
import { WidgetManager } from './manager';
import { DOMWidgetModel } from '@jupyter-widgets/base';
/**
* A renderer for widgets.
*/
export class WidgetRenderer extends Panel
implements IRenderMime.IRenderer, IDisposable {
constructor(options: IRenderMime.IRendererOptions, manager?: WidgetManager) {
super();
this.mimeType = options.mimeType;
if (manager) {
this.manager = manager;
}
}
/**
* The widget manager.
*/
set manager(value: WidgetManager) {
value.restored.connect(this._rerender, this);
this._manager.resolve(value);
}
async renderModel(model: IRenderMime.IMimeModel): Promise<void> {
const source: any = model.data[this.mimeType];
// Let's be optimistic, and hope the widget state will come later.
this.node.textContent = 'Loading widget...';
const manager = await this._manager.promise;
// If there is no model id, the view was removed, so hide the node.
if (source.model_id === '') {
this.hide();
return Promise.resolve();
}
let wModel: DOMWidgetModel;
try {
// Presume we have a DOMWidgetModel. Should we check for sure?
wModel = (await manager.get_model(source.model_id)) as DOMWidgetModel;
} catch (err) {
if (manager.restoredStatus) {
// The manager has been restored, so this error won't be going away.
this.node.textContent = 'Error displaying widget: model not found';
this.addClass('jupyter-widgets');
console.error(err);
return;
}
// Store the model for a possible rerender
this._rerenderMimeModel = model;
return;
}
// Successful getting the model, so we don't need to try to rerender.
this._rerenderMimeModel = null;
let widget: LuminoWidget;
try {
widget = (await manager.create_view(wModel)).pWidget;
} catch (err) {
this.node.textContent = 'Error displaying widget';
this.addClass('jupyter-widgets');
console.error(err);
return;
}
// Clear any previous loading message.
this.node.textContent = '';
this.addWidget(widget);
// When the widget is disposed, hide this container and make sure we
// change the output model to reflect the view was closed.
widget.disposed.connect(() => {
this.hide();
source.model_id = '';
});
}
/**
* Get whether the manager is disposed.
*
* #### Notes
* This is a read-only property.
*/
get isDisposed(): boolean {
return this._manager === null;
}
/**
* Dispose the resources held by the manager.
*/
dispose(): void {
if (this.isDisposed) {
return;
}
super.dispose();
this._manager = null!;
}
private _rerender(): void {
if (this._rerenderMimeModel) {
// Clear the error message
this.node.textContent = '';
this.removeClass('jupyter-widgets');
// Attempt to rerender.
this.renderModel(this._rerenderMimeModel);
}
}
/**
* The mimetype being rendered.
*/
readonly mimeType: string;
private _manager = new PromiseDelegate<WidgetManager>();
private _rerenderMimeModel: IRenderMime.IMimeModel | null = null;
}