diff --git a/IPython/html/static/widgets/js/manager.js b/IPython/html/static/widgets/js/manager.js index 3bf051d..13b2464 100644 --- a/IPython/html/static/widgets/js/manager.js +++ b/IPython/html/static/widgets/js/manager.js @@ -88,38 +88,32 @@ define([ /** * Displays a view for a particular model. */ - var that = this; - return new Promise(function(resolve, reject) { - var cell = that.get_msg_cell(msg.parent_header.msg_id); - if (cell === null) { - reject(new Error("Could not determine where the display" + - " message was from. Widget will not be displayed")); - } else { - return that.display_view_in_cell(cell, model) - .catch(function(error) { - reject(new utils.WrappedError('View could not be displayed.', error)); - }); - } - }); + var cell = this.get_msg_cell(msg.parent_header.msg_id); + if (cell === null) { + return Promise.reject(new Error("Could not determine where the display" + + " message was from. Widget will not be displayed")); + } else { + return this.display_view_in_cell(cell, model) + .catch(utils.reject('View could not be displayed.', true)); + } }; WidgetManager.prototype.display_view_in_cell = function(cell, model) { // Displays a view in a cell. - var that = this; - return new Promise(function(resolve, reject) { - if (cell.display_widget_view) { - cell.display_widget_view(that.create_view(model, {cell: cell})) - .then(function(view) { - that._handle_display_view(view); - view.trigger('displayed'); - resolve(view); - }, function(error) { - reject(new utils.WrappedError('Could not create or display view', error)); - }); - } else { - reject(new Error('Cell does not have a `display_widget_view` method')); - } - }); + if (cell.display_widget_view) { + var that = this; + return cell.display_widget_view(this.create_view(model, { + cell: cell, + // Only set cell_index when view is displayed as directly. + cell_index: that.notebook.find_cell_index(cell), + })).then(function(view) { + that._handle_display_view(view); + view.trigger('displayed'); + resolve(view); + }).catch(utils.reject('Could not create or display view', true)); + } else { + return Promise.reject(new Error('Cell does not have a `display_widget_view` method')); + } }; WidgetManager.prototype._handle_display_view = function (view) { @@ -315,7 +309,7 @@ define([ // Dictionary of options with the following contents: // only_displayed: (optional) boolean=false // Only return models with one or more displayed views. - // not_alive: (optional) boolean=false + // not_live: (optional) boolean=false // Include models that have comms with severed connections. // // Returns @@ -331,8 +325,8 @@ define([ // If the model has one or more views defined for it, // consider it displayed. var displayed_flag = !(options && options.only_displayed) || Object.keys(model.views).length > 0; - var alive_flag = (options && options.not_alive) || model.comm_alive; - if (displayed_flag && alive_flag) { + var live_flag = (options && options.not_live) || model.comm_live; + if (displayed_flag && live_flag) { state[model_id] = { model_name: model.name, model_module: model.module, @@ -344,13 +338,8 @@ define([ for (var id in model.views) { if (model.views.hasOwnProperty(id)) { var view = model.views[id]; - var cell = view.options.cell; - - // Only store the cell reference if this view is a top level - // child of the cell. - if (cell.widget_views.indexOf(view) != -1) { - var cell_index = that.notebook.find_cell_index(cell); - state[model_id].views.push(cell_index); + if (view.options.cell_index) { + state[model_id].views.push(view.options.cell_index); } } } @@ -358,7 +347,7 @@ define([ } } return state; - }); + }).catch(utils.reject('Could not get state of widget manager', true)); }; WidgetManager.prototype.set_state = function(state) { @@ -383,7 +372,7 @@ define([ kernel.comm_manager.register_comm(new_comm); // Create the model using the recreated comm. When the model is - // created we don't know yet if the comm is valid so set_comm_alive + // created we don't know yet if the comm is valid so set_comm_live // false. Once we receive the first state push from the back-end // we know the comm is alive. var views = kernel.widget_manager.create_model({ @@ -392,12 +381,12 @@ define([ model_module: state[model_id].model_module}) .then(function(model) { - model.set_comm_alive(false); + model.set_comm_live(false); var view_promise = Promise.resolve().then(function() { return model.set_state(state[model.id].state); }).then(function() { model.request_state().then(function() { - model.set_comm_alive(true); + model.set_comm_live(true); }); // Display the views of the model. diff --git a/IPython/html/static/widgets/js/widget.js b/IPython/html/static/widgets/js/widget.js index 7cf0fe1..01f5007 100644 --- a/IPython/html/static/widgets/js/widget.js +++ b/IPython/html/static/widgets/js/widget.js @@ -31,6 +31,7 @@ define(["widgets/js/manager", this.state_lock = null; this.id = model_id; this.views = {}; + this._resolve_received_state = {}; if (comm !== undefined) { // Remember comm associated with the model. @@ -42,9 +43,9 @@ define(["widgets/js/manager", comm.on_msg($.proxy(this._handle_comm_msg, this)); // Assume the comm is alive. - this.set_comm_alive(true); + this.set_comm_live(true); } else { - this.set_comm_alive(false); + this.set_comm_live(false); } return Backbone.Model.apply(this); }, @@ -69,24 +70,24 @@ define(["widgets/js/manager", return; } + var msg_id = this.comm.send({method: 'request_state'}, callbacks || this.widget_manager.callbacks()); + // Promise that is resolved when a state is received // from the back-end. var that = this; var received_state = new Promise(function(resolve) { - that._resolve_received_state = resolve; + that._resolve_received_state[msg_id] = resolve; }); - - this.comm.send({method: 'request_state'}, callbacks || this.widget_manager.callbacks()); return received_state; }, - set_comm_alive: function(alive) { + set_comm_live: function(live) { /** - * Change the comm_alive state of the model. + * Change the comm_live state of the model. */ - if (this.comm_alive === undefined || this.comm_alive != alive) { - this.comm_alive = alive; - this.trigger(alive ? 'comm_is_live' : 'comm_is_dead', {model: this}); + if (this.comm_live === undefined || this.comm_live != live) { + this.comm_live = live; + this.trigger(live ? 'comm:live' : 'comm:dead', {model: this}); } }, @@ -126,9 +127,17 @@ define(["widgets/js/manager", var that = this; switch (method) { case 'update': - this.state_change = this.state_change.then(function() { - return that.set_state(msg.content.data.state); - }).catch(utils.reject("Couldn't process update msg for model id '" + String(that.id) + "'", true)); + this.state_change = this.state_change + .then(function() { + return that.set_state(msg.content.data.state); + }).catch(utils.reject("Couldn't process update msg for model id '" + String(that.id) + "'", true)) + .then(function() { + var parent_id = msg.parent_header.msg_id; + if (that._resolve_received_state[parent_id] !== undefined) { + that._resolve_received_state[parent_id].call(); + delete that._resolve_received_state[parent_id]; + } + }).catch(utils.reject("Couldn't resolve state request promise.", true)); break; case 'custom': this.trigger('msg:custom', msg.content.data.content); @@ -150,11 +159,6 @@ define(["widgets/js/manager", } finally { that.state_lock = null; } - - if (that._resolve_received_state !== undefined) { - that._resolve_received_state(); - } - return Promise.resolve(); }, utils.reject("Couldn't set model state", true)); },