From 42d5e4e0e5f9012a141cf91bcdf683436842d890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Tue, 10 Sep 2019 14:07:07 -0400 Subject: [PATCH] end Legend.draw early when margin-redraw in-progress ... to avoid race conditions leading to wrong legend position and size. --- src/components/legend/draw.js | 9 ++++++--- src/plots/plots.js | 2 +- test/jasmine/tests/legend_test.js | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index cfa1bf6e0fe..23c2b1ce74a 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -93,8 +93,12 @@ module.exports = function draw(gd) { Lib.syncOrAsync([ Plots.previousPromises, function() { return computeLegendDimensions(gd, groups, traces); }, - function() { return expandMargin(gd); }, function() { + // IF expandMargin return a Promise (which is truthy), + // we're under a doAutoMargin redraw, so we don't have to + // draw the remaining pieces below + if(expandMargin(gd)) return; + var gs = fullLayout._size; var bw = opts.borderwidth; @@ -632,8 +636,7 @@ function expandMargin(gd) { var xanchor = getXanchor(opts); var yanchor = getYanchor(opts); - - Plots.autoMargin(gd, 'legend', { + return Plots.autoMargin(gd, 'legend', { x: opts.x, y: opts.y, l: opts._width * (FROM_TL[xanchor]), diff --git a/src/plots/plots.js b/src/plots/plots.js index 2ff4008a11d..b34c025d72f 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -1863,7 +1863,7 @@ plots.autoMargin = function(gd, id, o) { } if(!fullLayout._replotting) { - plots.doAutoMargin(gd); + return plots.doAutoMargin(gd); } } }; diff --git a/test/jasmine/tests/legend_test.js b/test/jasmine/tests/legend_test.js index e87768a8279..39c3ec695ba 100644 --- a/test/jasmine/tests/legend_test.js +++ b/test/jasmine/tests/legend_test.js @@ -715,6 +715,34 @@ describe('legend relayout update', function() { .then(done); }); }); + + it('should make legend fit in graph viewport', function(done) { + var fig = Lib.extendDeep({}, require('@mocks/legend_negative_x.json')); + + function _assert(msg, xy, wh) { + return function() { + var fullLayout = gd._fullLayout; + var legend3 = d3.select('g.legend'); + var bg3 = legend3.select('rect.bg'); + var translate = Drawing.getTranslate(legend3); + var x = translate.x; + var y = translate.y; + var w = +bg3.attr('width'); + var h = +bg3.attr('height'); + expect([x, y]).toBeWithinArray(xy, 25, msg + '| legend x,y'); + expect([w, h]).toBeWithinArray(wh, 25, msg + '| legend w,h'); + expect(x + w <= fullLayout.width).toBe(true, msg + '| fits in x'); + expect(y + h <= fullLayout.height).toBe(true, msg + '| fits in y'); + }; + } + + Plotly.plot(gd, fig) + .then(_assert('base', [5, 4.4], [512, 29])) + .then(function() { return Plotly.relayout(gd, 'legend.x', 0.8); }) + .then(_assert('after relayout almost to right edge', [188, 4.4], [512, 29])) + .catch(failTest) + .then(done); + }); }); describe('legend orientation change:', function() {