@@ -293,6 +293,22 @@ define([
293
293
} ;
294
294
295
295
WidgetManager . prototype . create_model = function ( options ) {
296
+ /**
297
+ * For backward compatibility. Custom widgets may be relying on the fact
298
+ * that create_model was creating a comm if none was provided in options.
299
+ * Unlike the old version of create_model, if no comm is passed,
300
+ * options.model_id is used to create the new comm.
301
+ */
302
+ console . warn ( 'WidgetManager.create_model is deprecated. Use WidgetManager.new_model' ) ;
303
+ if ( ! options . comm ) {
304
+ options . comm = this . comm_manager . new_comm ( 'ipython.widget' ,
305
+ { 'widget_class' : options . widget_class } ,
306
+ options . model_id ) ;
307
+ }
308
+ return this . new_model ( options ) ;
309
+ }
310
+
311
+ WidgetManager . prototype . new_model = function ( options ) {
296
312
/**
297
313
* Create and return a promise for a new widget model
298
314
*
@@ -302,7 +318,7 @@ define([
302
318
* Example
303
319
* --------
304
320
* JS:
305
- * IPython.notebook.kernel.widget_manager.create_model ({
321
+ * IPython.notebook.kernel.widget_manager.new_model ({
306
322
* model_name: 'WidgetModel',
307
323
* widget_class: 'ipywidgets.IntSlider'
308
324
* })
@@ -320,19 +336,19 @@ define([
320
336
* widget_class: (optional) string
321
337
* Target name of the widget in the back-end.
322
338
* comm: (optional) Comm
339
+ * Comm object associated with the widget.
340
+ * model_id: (optional) string
341
+ * If not provided, the comm id is used.
323
342
*
324
- * Create a comm if it wasn't provided.
343
+ * Either a comm or a model_id must be provided.
325
344
*/
326
- var comm = options . comm ;
327
- if ( ! comm ) {
328
- comm = this . comm_manager . new_comm ( 'ipython.widget' , { 'widget_class' : options . widget_class } ) ;
329
- }
330
-
331
345
var that = this ;
332
- var model_id = comm . comm_id ;
333
- var model_promise = utils . load_class ( options . model_name , options . model_module , WidgetManager . _model_types )
346
+ var model_id = options . model_id || options . comm . comm_id ;
347
+ var model_promise = utils . load_class ( options . model_name ,
348
+ options . model_module ,
349
+ WidgetManager . _model_types )
334
350
. then ( function ( ModelType ) {
335
- var widget_model = new ModelType ( that , model_id , comm ) ;
351
+ var widget_model = new ModelType ( that , model_id , options . comm ) ;
336
352
widget_model . once ( 'comm:close' , function ( ) {
337
353
delete that . _models [ model_id ] ;
338
354
} ) ;
@@ -423,30 +439,34 @@ define([
423
439
return this . _get_connected_kernel ( ) . then ( function ( kernel ) {
424
440
425
441
// Recreate all the widget models for the given notebook state.
426
- var all_models = Promise . all ( _ . map ( Object . keys ( state ) , function ( model_id ) {
427
- // Recreate a comm using the widget's model id (model_id == comm_id).
428
- var new_comm = new comm . Comm ( kernel . widget_manager . comm_target_name , model_id ) ;
429
- kernel . comm_manager . register_comm ( new_comm ) ;
430
-
431
- // Create the model using the recreated comm. When the model is
432
- // created we don't know yet if the comm is valid so set_comm_live
433
- // false. Once we receive the first state push from the back-end
434
- // we know the comm is alive.
435
- return kernel . widget_manager . create_model ( {
436
- comm : new_comm ,
437
- model_name : state [ model_id ] . model_name ,
438
- model_module : state [ model_id ] . model_module ,
439
- } ) . then ( function ( model ) {
440
- model . set_comm_live ( false ) ;
441
- return model . _deserialize_state ( state [ model . id ] . state ) . then ( function ( state ) {
442
- model . set_state ( state ) ;
443
- return model . request_state ( ) . then ( function ( ) {
444
- model . set_comm_live ( true ) ;
445
- return model ;
442
+ var all_models = that . _get_comm_info ( kernel ) . then ( function ( live_comms ) {
443
+ return Promise . all ( _ . map ( Object . keys ( state ) , function ( model_id ) {
444
+ if ( live_comms . hasOwnProperty ( model_id ) ) { // live comm
445
+ var new_comm = new comm . Comm ( kernel . widget_manager . comm_target_name , model_id ) ;
446
+ kernel . comm_manager . register_comm ( new_comm ) ;
447
+ return kernel . widget_manager . new_model ( {
448
+ comm : new_comm ,
449
+ model_name : state [ model_id ] . model_name ,
450
+ model_module : state [ model_id ] . model_module ,
451
+ } ) . then ( function ( model ) {
452
+ return model . request_state ( ) . then ( function ( ) {
453
+ return model ;
454
+ } ) ;
446
455
} ) ;
447
- } ) ;
448
- } ) ;
449
- } , this ) ) ;
456
+ } else { // dead comm
457
+ return kernel . widget_manager . new_model ( {
458
+ model_id : model_id ,
459
+ model_name : state [ model_id ] . model_name ,
460
+ model_module : state [ model_id ] . model_module ,
461
+ } ) . then ( function ( model ) {
462
+ return model . _deserialize_state ( state [ model_id ] . state ) . then ( function ( state ) {
463
+ model . set_state ( state ) ;
464
+ return model ;
465
+ } ) ;
466
+ } ) ;
467
+ }
468
+ } ) ) ;
469
+ } ) ;
450
470
451
471
// Display all the views
452
472
return all_models . then ( function ( models ) {
@@ -480,6 +500,35 @@ define([
480
500
} ) ;
481
501
} ;
482
502
503
+ WidgetManager . prototype . _get_comm_info = function ( kernel ) {
504
+ /**
505
+ * Gets a promise for the open comms in the backend
506
+ */
507
+
508
+ // Version using the comm_list_[request/reply] shell message.
509
+ /*var that = this;
510
+ return new Promise(function(resolve, reject) {
511
+ kernel.comm_info(function(msg) {
512
+ resolve(msg['content']['comms']);
513
+ });
514
+ });*/
515
+
516
+ // Workaround for absence of comm_list_[request/reply] shell message.
517
+ // Create a new widget that gives the comm list and commits suicide.
518
+ var that = this ;
519
+ return new Promise ( function ( resolve , reject ) {
520
+ var comm = that . comm_manager . new_comm ( 'ipython.widget' ,
521
+ { 'widget_class' : 'ipywidgets.CommInfo' } ,
522
+ 'comm_info' ) ;
523
+ comm . on_msg ( function ( msg ) {
524
+ var data = msg . content . data ;
525
+ if ( data . content && data . method === 'custom' ) {
526
+ resolve ( data . content . comms ) ;
527
+ }
528
+ } ) ;
529
+ } ) ;
530
+ } ;
531
+
483
532
// Backwards compatibility.
484
533
IPython . WidgetManager = WidgetManager ;
485
534
0 commit comments