##// END OF EJS Templates
Updated comments to new style.
Jonathan Frederic -
Show More
@@ -1,446 +1,458 b''
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 define([
4 define([
5 "underscore",
5 "underscore",
6 "backbone",
6 "backbone",
7 "jquery",
7 "jquery",
8 "base/js/utils",
8 "base/js/utils",
9 "base/js/namespace",
9 "base/js/namespace",
10 "services/kernels/comm"
10 "services/kernels/comm"
11 ], function (_, Backbone, $, utils, IPython, comm) {
11 ], function (_, Backbone, $, utils, IPython, comm) {
12 "use strict";
12 "use strict";
13 //--------------------------------------------------------------------
13 //--------------------------------------------------------------------
14 // WidgetManager class
14 // WidgetManager class
15 //--------------------------------------------------------------------
15 //--------------------------------------------------------------------
16 var WidgetManager = function (comm_manager, notebook) {
16 var WidgetManager = function (comm_manager, notebook) {
17 /**
17 /**
18 * Public constructor
18 * Public constructor
19 */
19 */
20 WidgetManager._managers.push(this);
20 WidgetManager._managers.push(this);
21
21
22 // Attach a comm manager to the
22 // Attach a comm manager to the
23 this.keyboard_manager = notebook.keyboard_manager;
23 this.keyboard_manager = notebook.keyboard_manager;
24 this.notebook = notebook;
24 this.notebook = notebook;
25 this.comm_manager = comm_manager;
25 this.comm_manager = comm_manager;
26 this.comm_target_name = 'ipython.widget';
26 this.comm_target_name = 'ipython.widget';
27 this._models = {}; /* Dictionary of model ids and model instance promises */
27 this._models = {}; /* Dictionary of model ids and model instance promises */
28
28
29 // Register with the comm manager.
29 // Register with the comm manager.
30 this.comm_manager.register_target(this.comm_target_name, $.proxy(this._handle_comm_open, this));
30 this.comm_manager.register_target(this.comm_target_name, $.proxy(this._handle_comm_open, this));
31
31
32 // Load the initial state of the widget manager if a load callback was
32 // Load the initial state of the widget manager if a load callback was
33 // registered.
33 // registered.
34 var that = this;
34 var that = this;
35 if (WidgetManager._load_callback) {
35 if (WidgetManager._load_callback) {
36 Promise.resolve(WidgetManager._load_callback.call(this)).then(function(state) {
36 Promise.resolve(WidgetManager._load_callback.call(this)).then(function(state) {
37 that.set_state(state);
37 that.set_state(state);
38 }).catch(utils.reject('Error loading widget manager state', true));
38 }).catch(utils.reject('Error loading widget manager state', true));
39 }
39 }
40
40
41 // Setup state saving code.
41 // Setup state saving code.
42 this.notebook.events.on('before_save.Notebook', function() {
42 this.notebook.events.on('before_save.Notebook', function() {
43 var save_callback = WidgetManager._save_callback;
43 var save_callback = WidgetManager._save_callback;
44 var options = WidgetManager._get_state_options;
44 var options = WidgetManager._get_state_options;
45 if (save_callback) {
45 if (save_callback) {
46 that.get_state(options).then(function(state) {
46 that.get_state(options).then(function(state) {
47 save_callback.call(that, state);
47 save_callback.call(that, state);
48 }).catch(utils.reject('Could not call widget save state callback.', true));
48 }).catch(utils.reject('Could not call widget save state callback.', true));
49 }
49 }
50 });
50 });
51 };
51 };
52
52
53 //--------------------------------------------------------------------
53 //--------------------------------------------------------------------
54 // Class level
54 // Class level
55 //--------------------------------------------------------------------
55 //--------------------------------------------------------------------
56 WidgetManager._model_types = {}; /* Dictionary of model type names (target_name) and model types. */
56 WidgetManager._model_types = {}; /* Dictionary of model type names (target_name) and model types. */
57 WidgetManager._view_types = {}; /* Dictionary of view names and view types. */
57 WidgetManager._view_types = {}; /* Dictionary of view names and view types. */
58 WidgetManager._managers = []; /* List of widget managers */
58 WidgetManager._managers = []; /* List of widget managers */
59 WidgetManager._load_callback = null;
59 WidgetManager._load_callback = null;
60 WidgetManager._save_callback = null;
60 WidgetManager._save_callback = null;
61
61
62 WidgetManager.register_widget_model = function (model_name, model_type) {
62 WidgetManager.register_widget_model = function (model_name, model_type) {
63 // Registers a widget model by name.
63 /**
64 * Registers a widget model by name.
65 */
64 WidgetManager._model_types[model_name] = model_type;
66 WidgetManager._model_types[model_name] = model_type;
65 };
67 };
66
68
67 WidgetManager.register_widget_view = function (view_name, view_type) {
69 WidgetManager.register_widget_view = function (view_name, view_type) {
68 // Registers a widget view by name.
70 /**
71 * Registers a widget view by name.
72 */
69 WidgetManager._view_types[view_name] = view_type;
73 WidgetManager._view_types[view_name] = view_type;
70 };
74 };
71
75
72 WidgetManager.set_state_callbacks = function (load_callback, save_callback, options) {
76 WidgetManager.set_state_callbacks = function (load_callback, save_callback, options) {
73 // Registers callbacks for widget state persistence.
77 /**
74 //
78 * Registers callbacks for widget state persistence.
75 // Parameters
79 *
76 // ----------
80 * Parameters
77 // load_callback: function()
81 * ----------
78 // function that is called when the widget manager state should be
82 * load_callback: function()
79 // loaded. This function should return a promise for the widget
83 * function that is called when the widget manager state should be
80 // manager state. An empty state is an empty dictionary `{}`.
84 * loaded. This function should return a promise for the widget
81 // save_callback: function(state as dictionary)
85 * manager state. An empty state is an empty dictionary `{}`.
82 // function that is called when the notebook is saved or autosaved.
86 * save_callback: function(state as dictionary)
83 // The current state of the widget manager is passed in as the first
87 * function that is called when the notebook is saved or autosaved.
84 // argument.
88 * The current state of the widget manager is passed in as the first
89 * argument.
90 */
85 WidgetManager._load_callback = load_callback;
91 WidgetManager._load_callback = load_callback;
86 WidgetManager._save_callback = save_callback;
92 WidgetManager._save_callback = save_callback;
87 WidgetManager._get_state_options = options;
93 WidgetManager._get_state_options = options;
88
94
89 // Use the load callback to immediately load widget states.
95 // Use the load callback to immediately load widget states.
90 WidgetManager._managers.forEach(function(manager) {
96 WidgetManager._managers.forEach(function(manager) {
91 if (load_callback) {
97 if (load_callback) {
92 Promise.resolve(load_callback.call(manager)).then(function(state) {
98 Promise.resolve(load_callback.call(manager)).then(function(state) {
93 manager.set_state(state);
99 manager.set_state(state);
94 }).catch(utils.reject('Error loading widget manager state', true));
100 }).catch(utils.reject('Error loading widget manager state', true));
95 }
101 }
96 });
102 });
97 };
103 };
98
104
99 //--------------------------------------------------------------------
105 //--------------------------------------------------------------------
100 // Instance level
106 // Instance level
101 //--------------------------------------------------------------------
107 //--------------------------------------------------------------------
102 WidgetManager.prototype.display_view = function(msg, model) {
108 WidgetManager.prototype.display_view = function(msg, model) {
103 /**
109 /**
104 * Displays a view for a particular model.
110 * Displays a view for a particular model.
105 */
111 */
106 var cell = this.get_msg_cell(msg.parent_header.msg_id);
112 var cell = this.get_msg_cell(msg.parent_header.msg_id);
107 if (cell === null) {
113 if (cell === null) {
108 return Promise.reject(new Error("Could not determine where the display" +
114 return Promise.reject(new Error("Could not determine where the display" +
109 " message was from. Widget will not be displayed"));
115 " message was from. Widget will not be displayed"));
110 } else {
116 } else {
111 return this.display_view_in_cell(cell, model)
117 return this.display_view_in_cell(cell, model)
112 .catch(utils.reject('Could not display view', true));
118 .catch(utils.reject('Could not display view', true));
113 }
119 }
114 };
120 };
115
121
116 WidgetManager.prototype.display_view_in_cell = function(cell, model) {
122 WidgetManager.prototype.display_view_in_cell = function(cell, model) {
117 // Displays a view in a cell.
123 // Displays a view in a cell.
118 if (cell.display_widget_view) {
124 if (cell.display_widget_view) {
119 var that = this;
125 var that = this;
120 return cell.display_widget_view(this.create_view(model, {
126 return cell.display_widget_view(this.create_view(model, {
121 cell: cell,
127 cell: cell,
122 // Only set cell_index when view is displayed as directly.
128 // Only set cell_index when view is displayed as directly.
123 cell_index: that.notebook.find_cell_index(cell),
129 cell_index: that.notebook.find_cell_index(cell),
124 })).then(function(view) {
130 })).then(function(view) {
125 that._handle_display_view(view);
131 that._handle_display_view(view);
126 view.trigger('displayed');
132 view.trigger('displayed');
127 resolve(view);
133 resolve(view);
128 }).catch(utils.reject('Could not create or display view', true));
134 }).catch(utils.reject('Could not create or display view', true));
129 } else {
135 } else {
130 return Promise.reject(new Error('Cell does not have a `display_widget_view` method'));
136 return Promise.reject(new Error('Cell does not have a `display_widget_view` method'));
131 }
137 }
132 };
138 };
133
139
134 WidgetManager.prototype._handle_display_view = function (view) {
140 WidgetManager.prototype._handle_display_view = function (view) {
135 /**
141 /**
136 * Have the IPython keyboard manager disable its event
142 * Have the IPython keyboard manager disable its event
137 * handling so the widget can capture keyboard input.
143 * handling so the widget can capture keyboard input.
138 * Note, this is only done on the outer most widgets.
144 * Note, this is only done on the outer most widgets.
139 */
145 */
140 if (this.keyboard_manager) {
146 if (this.keyboard_manager) {
141 this.keyboard_manager.register_events(view.$el);
147 this.keyboard_manager.register_events(view.$el);
142
148
143 if (view.additional_elements) {
149 if (view.additional_elements) {
144 for (var i = 0; i < view.additional_elements.length; i++) {
150 for (var i = 0; i < view.additional_elements.length; i++) {
145 this.keyboard_manager.register_events(view.additional_elements[i]);
151 this.keyboard_manager.register_events(view.additional_elements[i]);
146 }
152 }
147 }
153 }
148 }
154 }
149 };
155 };
150
156
151 WidgetManager.prototype.create_view = function(model, options) {
157 WidgetManager.prototype.create_view = function(model, options) {
152 /**
158 /**
153 * Creates a promise for a view of a given model
159 * Creates a promise for a view of a given model
154 *
160 *
155 * Make sure the view creation is not out of order with
161 * Make sure the view creation is not out of order with
156 * any state updates.
162 * any state updates.
157 */
163 */
158 model.state_change = model.state_change.then(function() {
164 model.state_change = model.state_change.then(function() {
159
165
160 return utils.load_class(model.get('_view_name'), model.get('_view_module'),
166 return utils.load_class(model.get('_view_name'), model.get('_view_module'),
161 WidgetManager._view_types).then(function(ViewType) {
167 WidgetManager._view_types).then(function(ViewType) {
162
168
163 // If a view is passed into the method, use that view's cell as
169 // If a view is passed into the method, use that view's cell as
164 // the cell for the view that is created.
170 // the cell for the view that is created.
165 options = options || {};
171 options = options || {};
166 if (options.parent !== undefined) {
172 if (options.parent !== undefined) {
167 options.cell = options.parent.options.cell;
173 options.cell = options.parent.options.cell;
168 }
174 }
169 // Create and render the view...
175 // Create and render the view...
170 var parameters = {model: model, options: options};
176 var parameters = {model: model, options: options};
171 var view = new ViewType(parameters);
177 var view = new ViewType(parameters);
172 view.listenTo(model, 'destroy', view.remove);
178 view.listenTo(model, 'destroy', view.remove);
173 return Promise.resolve(view.render()).then(function() {return view;});
179 return Promise.resolve(view.render()).then(function() {return view;});
174 }).catch(utils.reject("Couldn't create a view for model id '" + String(model.id) + "'", true));
180 }).catch(utils.reject("Couldn't create a view for model id '" + String(model.id) + "'", true));
175 });
181 });
176 model.views[utils.uuid()] = model.state_change;
182 model.views[utils.uuid()] = model.state_change;
177 return model.state_change;
183 return model.state_change;
178 };
184 };
179
185
180 WidgetManager.prototype.get_msg_cell = function (msg_id) {
186 WidgetManager.prototype.get_msg_cell = function (msg_id) {
181 var cell = null;
187 var cell = null;
182 // First, check to see if the msg was triggered by cell execution.
188 // First, check to see if the msg was triggered by cell execution.
183 if (this.notebook) {
189 if (this.notebook) {
184 cell = this.notebook.get_msg_cell(msg_id);
190 cell = this.notebook.get_msg_cell(msg_id);
185 }
191 }
186 if (cell !== null) {
192 if (cell !== null) {
187 return cell;
193 return cell;
188 }
194 }
189 // Second, check to see if a get_cell callback was defined
195 // Second, check to see if a get_cell callback was defined
190 // for the message. get_cell callbacks are registered for
196 // for the message. get_cell callbacks are registered for
191 // widget messages, so this block is actually checking to see if the
197 // widget messages, so this block is actually checking to see if the
192 // message was triggered by a widget.
198 // message was triggered by a widget.
193 var kernel = this.comm_manager.kernel;
199 var kernel = this.comm_manager.kernel;
194 if (kernel) {
200 if (kernel) {
195 var callbacks = kernel.get_callbacks_for_msg(msg_id);
201 var callbacks = kernel.get_callbacks_for_msg(msg_id);
196 if (callbacks && callbacks.iopub &&
202 if (callbacks && callbacks.iopub &&
197 callbacks.iopub.get_cell !== undefined) {
203 callbacks.iopub.get_cell !== undefined) {
198 return callbacks.iopub.get_cell();
204 return callbacks.iopub.get_cell();
199 }
205 }
200 }
206 }
201
207
202 // Not triggered by a cell or widget (no get_cell callback
208 // Not triggered by a cell or widget (no get_cell callback
203 // exists).
209 // exists).
204 return null;
210 return null;
205 };
211 };
206
212
207 WidgetManager.prototype.callbacks = function (view) {
213 WidgetManager.prototype.callbacks = function (view) {
208 /**
214 /**
209 * callback handlers specific a view
215 * callback handlers specific a view
210 */
216 */
211 var callbacks = {};
217 var callbacks = {};
212 if (view && view.options.cell) {
218 if (view && view.options.cell) {
213
219
214 // Try to get output handlers
220 // Try to get output handlers
215 var cell = view.options.cell;
221 var cell = view.options.cell;
216 var handle_output = null;
222 var handle_output = null;
217 var handle_clear_output = null;
223 var handle_clear_output = null;
218 if (cell.output_area) {
224 if (cell.output_area) {
219 handle_output = $.proxy(cell.output_area.handle_output, cell.output_area);
225 handle_output = $.proxy(cell.output_area.handle_output, cell.output_area);
220 handle_clear_output = $.proxy(cell.output_area.handle_clear_output, cell.output_area);
226 handle_clear_output = $.proxy(cell.output_area.handle_clear_output, cell.output_area);
221 }
227 }
222
228
223 // Create callback dictionary using what is known
229 // Create callback dictionary using what is known
224 var that = this;
230 var that = this;
225 callbacks = {
231 callbacks = {
226 iopub : {
232 iopub : {
227 output : handle_output,
233 output : handle_output,
228 clear_output : handle_clear_output,
234 clear_output : handle_clear_output,
229
235
230 // Special function only registered by widget messages.
236 // Special function only registered by widget messages.
231 // Allows us to get the cell for a message so we know
237 // Allows us to get the cell for a message so we know
232 // where to add widgets if the code requires it.
238 // where to add widgets if the code requires it.
233 get_cell : function () {
239 get_cell : function () {
234 return cell;
240 return cell;
235 },
241 },
236 },
242 },
237 };
243 };
238 }
244 }
239 return callbacks;
245 return callbacks;
240 };
246 };
241
247
242 WidgetManager.prototype.get_model = function (model_id) {
248 WidgetManager.prototype.get_model = function (model_id) {
243 /**
249 /**
244 * Get a promise for a model by model id.
250 * Get a promise for a model by model id.
245 */
251 */
246 return this._models[model_id];
252 return this._models[model_id];
247 };
253 };
248
254
249 WidgetManager.prototype._handle_comm_open = function (comm, msg) {
255 WidgetManager.prototype._handle_comm_open = function (comm, msg) {
250 /**
256 /**
251 * Handle when a comm is opened.
257 * Handle when a comm is opened.
252 */
258 */
253 return this.create_model({
259 return this.create_model({
254 model_name: msg.content.data.model_name,
260 model_name: msg.content.data.model_name,
255 model_module: msg.content.data.model_module,
261 model_module: msg.content.data.model_module,
256 comm: comm}).catch(utils.reject("Couldn't create a model.", true));
262 comm: comm}).catch(utils.reject("Couldn't create a model.", true));
257 };
263 };
258
264
259 WidgetManager.prototype.create_model = function (options) {
265 WidgetManager.prototype.create_model = function (options) {
260 /**
266 /**
261 * Create and return a promise for a new widget model
267 * Create and return a promise for a new widget model
262 *
268 *
263 * Minimally, one must provide the model_name and widget_class
269 * Minimally, one must provide the model_name and widget_class
264 * parameters to create a model from Javascript.
270 * parameters to create a model from Javascript.
265 *
271 *
266 * Example
272 * Example
267 * --------
273 * --------
268 * JS:
274 * JS:
269 * IPython.notebook.kernel.widget_manager.create_model({
275 * IPython.notebook.kernel.widget_manager.create_model({
270 * model_name: 'WidgetModel',
276 * model_name: 'WidgetModel',
271 * widget_class: 'IPython.html.widgets.widget_int.IntSlider'})
277 * widget_class: 'IPython.html.widgets.widget_int.IntSlider'})
272 * .then(function(model) { console.log('Create success!', model); },
278 * .then(function(model) { console.log('Create success!', model); },
273 * $.proxy(console.error, console));
279 * $.proxy(console.error, console));
274 *
280 *
275 * Parameters
281 * Parameters
276 * ----------
282 * ----------
277 * options: dictionary
283 * options: dictionary
278 * Dictionary of options with the following contents:
284 * Dictionary of options with the following contents:
279 * model_name: string
285 * model_name: string
280 * Target name of the widget model to create.
286 * Target name of the widget model to create.
281 * model_module: (optional) string
287 * model_module: (optional) string
282 * Module name of the widget model to create.
288 * Module name of the widget model to create.
283 * widget_class: (optional) string
289 * widget_class: (optional) string
284 * Target name of the widget in the back-end.
290 * Target name of the widget in the back-end.
285 * comm: (optional) Comm
291 * comm: (optional) Comm
286 *
292 *
287 * Create a comm if it wasn't provided.
293 * Create a comm if it wasn't provided.
288 */
294 */
289 var comm = options.comm;
295 var comm = options.comm;
290 if (!comm) {
296 if (!comm) {
291 comm = this.comm_manager.new_comm('ipython.widget', {'widget_class': options.widget_class});
297 comm = this.comm_manager.new_comm('ipython.widget', {'widget_class': options.widget_class});
292 }
298 }
293
299
294 var that = this;
300 var that = this;
295 var model_id = comm.comm_id;
301 var model_id = comm.comm_id;
296 var model_promise = utils.load_class(options.model_name, options.model_module, WidgetManager._model_types)
302 var model_promise = utils.load_class(options.model_name, options.model_module, WidgetManager._model_types)
297 .then(function(ModelType) {
303 .then(function(ModelType) {
298 var widget_model = new ModelType(that, model_id, comm);
304 var widget_model = new ModelType(that, model_id, comm);
299 widget_model.once('comm:close', function () {
305 widget_model.once('comm:close', function () {
300 delete that._models[model_id];
306 delete that._models[model_id];
301 });
307 });
302 widget_model.name = options.model_name;
308 widget_model.name = options.model_name;
303 widget_model.module = options.model_module;
309 widget_model.module = options.model_module;
304 return widget_model;
310 return widget_model;
305
311
306 }, function(error) {
312 }, function(error) {
307 delete that._models[model_id];
313 delete that._models[model_id];
308 var wrapped_error = new utils.WrappedError("Couldn't create model", error);
314 var wrapped_error = new utils.WrappedError("Couldn't create model", error);
309 return Promise.reject(wrapped_error);
315 return Promise.reject(wrapped_error);
310 });
316 });
311 this._models[model_id] = model_promise;
317 this._models[model_id] = model_promise;
312 return model_promise;
318 return model_promise;
313 };
319 };
314
320
315 WidgetManager.prototype.get_state = function(options) {
321 WidgetManager.prototype.get_state = function(options) {
316 // Asynchronously get the state of the widget manager.
322 /**
317 //
323 * Asynchronously get the state of the widget manager.
318 // This includes all of the widget models and the cells that they are
324 *
319 // displayed in.
325 * This includes all of the widget models and the cells that they are
320 //
326 * displayed in.
321 // Parameters
327 *
322 // ----------
328 * Parameters
323 // options: dictionary
329 * ----------
324 // Dictionary of options with the following contents:
330 * options: dictionary
325 // only_displayed: (optional) boolean=false
331 * Dictionary of options with the following contents:
326 // Only return models with one or more displayed views.
332 * only_displayed: (optional) boolean=false
327 // not_live: (optional) boolean=false
333 * Only return models with one or more displayed views.
328 // Include models that have comms with severed connections.
334 * not_live: (optional) boolean=false
329 //
335 * Include models that have comms with severed connections.
330 // Returns
336 *
331 // -------
337 * Returns
332 // Promise for a state dictionary
338 * -------
339 * Promise for a state dictionary
340 */
333 var that = this;
341 var that = this;
334 return utils.resolve_promises_dict(this._models).then(function(models) {
342 return utils.resolve_promises_dict(this._models).then(function(models) {
335 var state = {};
343 var state = {};
336 for (var model_id in models) {
344 for (var model_id in models) {
337 if (models.hasOwnProperty(model_id)) {
345 if (models.hasOwnProperty(model_id)) {
338 var model = models[model_id];
346 var model = models[model_id];
339
347
340 // If the model has one or more views defined for it,
348 // If the model has one or more views defined for it,
341 // consider it displayed.
349 // consider it displayed.
342 var displayed_flag = !(options && options.only_displayed) || Object.keys(model.views).length > 0;
350 var displayed_flag = !(options && options.only_displayed) || Object.keys(model.views).length > 0;
343 var live_flag = (options && options.not_live) || model.comm_live;
351 var live_flag = (options && options.not_live) || model.comm_live;
344 if (displayed_flag && live_flag) {
352 if (displayed_flag && live_flag) {
345 state[model_id] = {
353 state[model_id] = {
346 model_name: model.name,
354 model_name: model.name,
347 model_module: model.module,
355 model_module: model.module,
348 state: model.get_state(),
356 state: model.get_state(),
349 views: [],
357 views: [],
350 };
358 };
351
359
352 // Get the views that are displayed *now*.
360 // Get the views that are displayed *now*.
353 for (var id in model.views) {
361 for (var id in model.views) {
354 if (model.views.hasOwnProperty(id)) {
362 if (model.views.hasOwnProperty(id)) {
355 var view = model.views[id];
363 var view = model.views[id];
356 if (view.options.cell_index) {
364 if (view.options.cell_index) {
357 state[model_id].views.push(view.options.cell_index);
365 state[model_id].views.push(view.options.cell_index);
358 }
366 }
359 }
367 }
360 }
368 }
361 }
369 }
362 }
370 }
363 }
371 }
364 return state;
372 return state;
365 }).catch(utils.reject('Could not get state of widget manager', true));
373 }).catch(utils.reject('Could not get state of widget manager', true));
366 };
374 };
367
375
368 WidgetManager.prototype.set_state = function(state) {
376 WidgetManager.prototype.set_state = function(state) {
369 // Set the notebook's state.
377 /**
370 //
378 * Set the notebook's state.
371 // Reconstructs all of the widget models and attempts to redisplay the
379 *
372 // widgets in the appropriate cells by cell index.
380 * Reconstructs all of the widget models and attempts to redisplay the
373
381 * widgets in the appropriate cells by cell index.
382 */
383
374 // Get the kernel when it's available.
384 // Get the kernel when it's available.
375 var that = this;
385 var that = this;
376 return this._get_connected_kernel().then(function(kernel) {
386 return this._get_connected_kernel().then(function(kernel) {
377
387
378 // Recreate all the widget models for the given state and
388 // Recreate all the widget models for the given state and
379 // display the views.
389 // display the views.
380 that.all_views = [];
390 that.all_views = [];
381 var model_ids = Object.keys(state);
391 var model_ids = Object.keys(state);
382 for (var i = 0; i < model_ids.length; i++) {
392 for (var i = 0; i < model_ids.length; i++) {
383 var model_id = model_ids[i];
393 var model_id = model_ids[i];
384
394
385 // Recreate a comm using the widget's model id (model_id == comm_id).
395 // Recreate a comm using the widget's model id (model_id == comm_id).
386 var new_comm = new comm.Comm(kernel.widget_manager.comm_target_name, model_id);
396 var new_comm = new comm.Comm(kernel.widget_manager.comm_target_name, model_id);
387 kernel.comm_manager.register_comm(new_comm);
397 kernel.comm_manager.register_comm(new_comm);
388
398
389 // Create the model using the recreated comm. When the model is
399 // Create the model using the recreated comm. When the model is
390 // created we don't know yet if the comm is valid so set_comm_live
400 // created we don't know yet if the comm is valid so set_comm_live
391 // false. Once we receive the first state push from the back-end
401 // false. Once we receive the first state push from the back-end
392 // we know the comm is alive.
402 // we know the comm is alive.
393 var views = kernel.widget_manager.create_model({
403 var views = kernel.widget_manager.create_model({
394 comm: new_comm,
404 comm: new_comm,
395 model_name: state[model_id].model_name,
405 model_name: state[model_id].model_name,
396 model_module: state[model_id].model_module})
406 model_module: state[model_id].model_module})
397 .then(function(model) {
407 .then(function(model) {
398
408
399 model.set_comm_live(false);
409 model.set_comm_live(false);
400 var view_promise = Promise.resolve().then(function() {
410 var view_promise = Promise.resolve().then(function() {
401 return model.set_state(state[model.id].state);
411 return model.set_state(state[model.id].state);
402 }).then(function() {
412 }).then(function() {
403 model.request_state().then(function() {
413 model.request_state().then(function() {
404 model.set_comm_live(true);
414 model.set_comm_live(true);
405 });
415 });
406
416
407 // Display the views of the model.
417 // Display the views of the model.
408 var views = [];
418 var views = [];
409 var model_views = state[model.id].views;
419 var model_views = state[model.id].views;
410 for (var j=0; j<model_views.length; j++) {
420 for (var j=0; j<model_views.length; j++) {
411 var cell_index = model_views[j];
421 var cell_index = model_views[j];
412 var cell = that.notebook.get_cell(cell_index);
422 var cell = that.notebook.get_cell(cell_index);
413 views.push(that.display_view_in_cell(cell, model));
423 views.push(that.display_view_in_cell(cell, model));
414 }
424 }
415 return Promise.all(views);
425 return Promise.all(views);
416 });
426 });
417 return view_promise;
427 return view_promise;
418 });
428 });
419 that.all_views.push(views);
429 that.all_views.push(views);
420 }
430 }
421 return Promise.all(that.all_views);
431 return Promise.all(that.all_views);
422 }).catch(utils.reject('Could not set widget manager state.', true));
432 }).catch(utils.reject('Could not set widget manager state.', true));
423 };
433 };
424
434
425 WidgetManager.prototype._get_connected_kernel = function() {
435 WidgetManager.prototype._get_connected_kernel = function() {
426 // Gets a promise for a connected kernel.
436 /**
437 * Gets a promise for a connected kernel
438 */
427 var that = this;
439 var that = this;
428 return new Promise(function(resolve, reject) {
440 return new Promise(function(resolve, reject) {
429 if (that.comm_manager &&
441 if (that.comm_manager &&
430 that.comm_manager.kernel &&
442 that.comm_manager.kernel &&
431 that.comm_manager.kernel.is_connected()) {
443 that.comm_manager.kernel.is_connected()) {
432
444
433 resolve(that.comm_manager.kernel);
445 resolve(that.comm_manager.kernel);
434 } else {
446 } else {
435 that.notebook.events.on('kernel_connected.Kernel', function(event, data) {
447 that.notebook.events.on('kernel_connected.Kernel', function(event, data) {
436 resolve(data.kernel);
448 resolve(data.kernel);
437 });
449 });
438 }
450 }
439 });
451 });
440 };
452 };
441
453
442 // Backwards compatibility.
454 // Backwards compatibility.
443 IPython.WidgetManager = WidgetManager;
455 IPython.WidgetManager = WidgetManager;
444
456
445 return {'WidgetManager': WidgetManager};
457 return {'WidgetManager': WidgetManager};
446 });
458 });
General Comments 0
You need to be logged in to leave comments. Login now