diff --git a/plugins/DebugEvents/js/main.js b/plugins/DebugEvents/js/main.js index 447332fbdf..83539ee64c 100644 --- a/plugins/DebugEvents/js/main.js +++ b/plugins/DebugEvents/js/main.js @@ -51,86 +51,89 @@ return declare( JBrowsePlugin, this.browser.afterMilestone( 'createTrack', function() { console.log("Milestone: createTrack"); }); - - + + dojo.subscribe("/jbrowse/v1/v/tracks/new", function(data){ console.log("Event: /jbrowse/v1/v/tracks/new",data); - }); + }); dojo.subscribe("/jbrowse/v1/v/tracks/show", function(data){ console.log("Event: /jbrowse/v1/v/tracks/show",data); - }); + }); dojo.subscribe("/jbrowse/v1/c/tracks/show", function(data){ console.log("Event: /jbrowse/v1/c/tracks/show",data); - }); + }); dojo.subscribe("/jbrowse/v1/v/tracks/hide", function(data){ console.log("Event: /jbrowse/v1/v/tracks/hide",data); - }); + }); dojo.subscribe("/jbrowse/v1/c/tracks/hide", function(data){ console.log("Event: /jbrowse/v1/c/tracks/hide",data); - }); + }); dojo.subscribe("/jbrowse/v1/v/tracks/hide", function(data){ console.log("Event: /jbrowse/v1/v/tracks/hide",data); - }); + }); dojo.subscribe("/jbrowse/v1/c/tracks/new", function(data){ console.log("Event: /jbrowse/v1/c/tracks/new",data); - }); + }); dojo.subscribe("/jbrowse/v1/n/tracks/new", function(data){ console.log("Event: /jbrowse/v1/n/tracks/new",data); - }); + }); dojo.subscribe("/jbrowse/v1/v/tracks/replace", function(data){ console.log("Event: /jbrowse/v1/v/tracks/replace",data); - }); + }); dojo.subscribe("/jbrowse/v1/c/tracks/replace", function(data){ console.log("Event: /jbrowse/v1/c/tracks/replace",data); - }); + }); dojo.subscribe("/jbrowse/v1/n/tracks/replace", function(data){ console.log("Event: /jbrowse/v1/n/tracks/replace",data); - }); + }); dojo.subscribe("/jbrowse/v1/v/tracks/delete", function(data){ console.log("Event: /jbrowse/v1/v/tracks/delete",data); - }); + }); dojo.subscribe("/jbrowse/v1/c/tracks/delete", function(data){ console.log("Event: /jbrowse/v1/c/tracks/delete",data); - }); + }); dojo.subscribe("/jbrowse/v1/n/tracks/delete", function(data){ console.log("Event: /jbrowse/v1/n/tracks/delete",data); - }); + }); dojo.subscribe("/jbrowse/v1/v/tracks/pin", function(data){ console.log("Event: /jbrowse/v1/v/tracks/pin",data); - }); + }); dojo.subscribe("/jbrowse/v1/c/tracks/pin", function(data){ console.log("Event: /jbrowse/v1/c/tracks/pin",data); - }); + }); dojo.subscribe("/jbrowse/v1/n/tracks/pin", function(data){ console.log("Event: /jbrowse/v1/n/tracks/pin",data); - }); + }); dojo.subscribe("/jbrowse/v1/v/tracks/unpin", function(data){ console.log("Event: /jbrowse/v1/v/tracks/unpin",data); - }); + }); dojo.subscribe("/jbrowse/v1/c/tracks/unpin", function(data){ console.log("Event: /jbrowse/v1/c/tracks/unpin",data); - }); + }); dojo.subscribe("/jbrowse/v1/n/tracks/unpin", function(data){ console.log("Event: /jbrowse/v1/n/tracks/unpin",data); - }); + }); dojo.subscribe("/jbrowse/v1/n/tracks/visibleChanged", function(data){ console.log("Event: /jbrowse/v1/n/tracks/visibleChanged",data); - }); + }); dojo.subscribe("/jbrowse/v1/n/navigate", function(data){ console.log("Event: /jbrowse/v1/n/navigate",data); - }); + }); dojo.subscribe("/jbrowse/v1/n/globalHighlightChanged", function(data){ console.log("Event: /jbrowse/v1/n/globalHighlightChanged",data); - }); + }); dojo.subscribe("/jbrowse/v1/n/tracks/redraw", function(data){ console.log("Event: /jbrowse/v1/n/tracks/redraw",data); - }); + }); + dojo.subscribe("/jbrowse/v1/n/tracks/redrawFinished", function(data){ + console.log("Event: /jbrowse/v1/n/tracks/redrawFinished",data); + }); dojo.subscribe("/jbrowse/v1/n/tracks/focus", function(data){ console.log("Event: /jbrowse/v1/n/tracks/focus",data); - }); + }); dojo.subscribe("/jbrowse/v1/n/tracks/unfocus", function(data){ console.log("Event: /jbrowse/v1/n/tracks/unfocus",data); - }); + }); } diff --git a/release-notes.txt b/release-notes.txt index 0af023b4b3..474c826e24 100644 --- a/release-notes.txt +++ b/release-notes.txt @@ -10,6 +10,10 @@ fast searching through large numbers of datasets. Thanks to @keiranmraine for the suggestion! (issue #752, @rbuels) + * There is now a new event named `/jbrowse/v1/n/tracks/redrawFinished` that fires after the + view is refreshed, when all of the visible tracks are finished drawing (or have errored). + Thanks to @scottcain for suggesting this. (issue #1027, @rbuels) + * Improve the calculation of feature density for GFF3Tabix and add new one for GFF3 in-memory. Thanks to @hkmoon for the suggestion! (issue #1039, issue #913, @cmdcolin) diff --git a/src/JBrowse/GenomeView.js b/src/JBrowse/GenomeView.js index dc3ebc9e76..51ed9219cc 100755 --- a/src/JBrowse/GenomeView.js +++ b/src/JBrowse/GenomeView.js @@ -2032,7 +2032,7 @@ trackHeightUpdate: function(trackName, height) { this.updateStaticElements({ height: this.getHeight() }); }, -showVisibleBlocks: function(updateHeight, pos, startX, endX) { +showVisibleBlocks: function(updateHeight, pos, startX, endX, finishCallback) { if (pos === undefined) pos = this.getPosition(); if (startX === undefined) startX = pos.x - (this.drawMargin * this.getWidth()); if (endX === undefined) endX = pos.x + ((1 + this.drawMargin) * this.getWidth()); @@ -2050,27 +2050,51 @@ showVisibleBlocks: function(updateHeight, pos, startX, endX) { Math.round(this.pxToBp(this.offset + (this.stripeCount * this.stripeWidth))); + let showingPromises = [] this.overviewTrackIterate(function(track, view) { - track.showRange(0, view.overviewStripes - 1, - view.ref.start-1, view.overviewStripeBases, - view.overviewBox.w / - (view.ref.end - view.ref.start)); - }); + showingPromises.push( new Promise((resolve,reject) => { + track.showRange( + 0, + view.overviewStripes - 1, + view.ref.start-1, + view.overviewStripeBases, + view.overviewBox.w / (view.ref.end - view.ref.start), + undefined, + undefined, + resolve, + ) + })) + }) this.trackIterate(function(track, view) { - track.showRange(leftVisible, rightVisible, - startBase, bpPerBlock, - view.pxPerBp, - containerStart, containerEnd); - }); + showingPromises.push( new Promise((resolve,reject) => { + track.showRange( + leftVisible, + rightVisible, + startBase, + bpPerBlock, + view.pxPerBp, + containerStart, + containerEnd, + resolve, + ) + })) + }) this.updateStaticElements({ - height: this.getHeight(), - width: this.getWidth(), - x: this.getX(), - y: this.getY() - }); + height: this.getHeight(), + width: this.getWidth(), + x: this.getX(), + y: this.getY() + }) + + this.browser.publish( '/jbrowse/v1/n/tracks/redraw' ) - this.browser.publish( '/jbrowse/v1/n/tracks/redraw' ); + const after = () => { + if (finishCallback) finishCallback() + this.browser.publish( '/jbrowse/v1/n/tracks/redrawFinished' ) + } + Promise.all(showingPromises) + .then(after, after) }, /** diff --git a/src/JBrowse/View/Track/BlockBased.js b/src/JBrowse/View/Track/BlockBased.js index 6c6a9d0459..17c360e923 100644 --- a/src/JBrowse/View/Track/BlockBased.js +++ b/src/JBrowse/View/Track/BlockBased.js @@ -273,7 +273,7 @@ return declare( [Component,DetailsMixin,FeatureFiltererMixin,Destroyable], showRange: function(first, last, startBase, bpPerBlock, scale, - containerStart, containerEnd) { + containerStart, containerEnd, finishCallback) { if( this.fatalError ) { this.showFatalError( this.fatalError ); @@ -296,18 +296,27 @@ return declare( [Component,DetailsMixin,FeatureFiltererMixin,Destroyable], var i, leftBase; var maxHeight = 0; + var blockShowingPromises = []; //fill left, including existing blocks (to get their heights) for (i = lastAttached; i >= first; i--) { leftBase = startBase + (bpPerBlock * (i - first)); - this._showBlock(i, leftBase, leftBase + bpPerBlock, scale, - containerStart, containerEnd); + blockShowingPromises.push( new Promise((resolve,reject) => { + this._showBlock(i, leftBase, leftBase + bpPerBlock, scale, + containerStart, containerEnd, resolve); + })) } //fill right for (i = lastAttached + 1; i <= last; i++) { leftBase = startBase + (bpPerBlock * (i - first)); - this._showBlock(i, leftBase, leftBase + bpPerBlock, scale, - containerStart, containerEnd); + blockShowingPromises.push( new Promise((resolve,reject) => { + this._showBlock(i, leftBase, leftBase + bpPerBlock, scale, + containerStart, containerEnd, resolve); + })) } + // if we have a finishing callback, call it when we have finished all our _showBlock calls + if( finishCallback ) + Promise.all(blockShowingPromises) + .then(finishCallback, finishCallback) //detach left blocks var destBlock = this.blocks[first]; @@ -514,14 +523,16 @@ return declare( [Component,DetailsMixin,FeatureFiltererMixin,Destroyable], }, _showBlock: function(blockIndex, startBase, endBase, scale, - containerStart, containerEnd) { + containerStart, containerEnd, finishCallback) { if ( this.empty || this.fatalError ) { this.heightUpdate( this.labelHeight ); + if (finishCallback) finishCallback(); return; } if (this.blocks[blockIndex]) { this.heightUpdate(this.blockHeights[blockIndex], blockIndex); + if (finishCallback) finishCallback(); return; } @@ -553,6 +564,7 @@ return declare( [Component,DetailsMixin,FeatureFiltererMixin,Destroyable], if( this.fatalError ) { this.fillBlockError( blockIndex, block ); + if (finishCallback) finishCallback(); return; } @@ -564,6 +576,8 @@ return declare( [Component,DetailsMixin,FeatureFiltererMixin,Destroyable], var finish = function() { if( block && loadMessage.parentNode ) block.domNode.removeChild( loadMessage ); + if( finishCallback ) + finishCallback() }; var viewargs = { diff --git a/src/JBrowse/View/Track/Combination.js b/src/JBrowse/View/Track/Combination.js index cf44c199a5..f8a853519e 100644 --- a/src/JBrowse/View/Track/Combination.js +++ b/src/JBrowse/View/Track/Combination.js @@ -715,7 +715,7 @@ sizeInit: function( numBlocks, widthPct, blockDelta ) { }, // Extends the BlockBased track's showRange function. -showRange: function(first, last, startBase, bpPerBlock, scale, containerStart, containerEnd) { +showRange: function(first, last, startBase, bpPerBlock, scale, containerStart, containerEnd, finishCallback) { this.range = {f: first, l: last, st: startBase, b: bpPerBlock, sc: scale, @@ -743,7 +743,7 @@ showRange: function(first, last, startBase, bpPerBlock, scale, containerStart, c if(reloadedStores.length && reloadedStores.indexOf(this._visible().store) != -1) { this.resultsTrack.clear(); } - this.resultsTrack.showRange(first, last, startBase, bpPerBlock, scale, containerStart, containerEnd); + this.resultsTrack.showRange(first, last, startBase, bpPerBlock, scale, containerStart, containerEnd, finishCallback); }), this.errorCallback);