Skip to content

Commit 13a15d1

Browse files
committed
improve cartesian trace delete pattern
... when corresponding module is gone from fullLayout._modules To do so, call plot methods of visible modules AND of recently deleted ones, by stashing list of module on plot after Cartesian.plot in each plotinfo object. Make sure to list unique 'plot method' NOT unique trace module as sometimes multiple module use same 'plot method'.
1 parent 156f127 commit 13a15d1

File tree

2 files changed

+58
-79
lines changed

2 files changed

+58
-79
lines changed

src/plots/cartesian/index.js

+34-71
Original file line numberDiff line numberDiff line change
@@ -179,106 +179,69 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) {
179179
};
180180

181181
function plotOne(gd, plotinfo, cdSubplot, transitionOpts, makeOnCompleteCallback) {
182-
var fullLayout = gd._fullLayout,
183-
modules = fullLayout._modules;
184-
185-
// remove old traces, then redraw everything
186-
//
187-
// TODO: scatterlayer is manually excluded from this since it knows how
188-
// to update instead of fully removing and redrawing every time. The
189-
// remaining plot traces should also be able to do this. Once implemented,
190-
// we won't need this - which should sometimes be a big speedup.
191-
if(plotinfo.plot) {
192-
plotinfo.plot.selectAll('g:not(.scatterlayer):not(.ohlclayer)').selectAll('g.trace').remove();
182+
var fullLayout = gd._fullLayout;
183+
var modules = fullLayout._modules;
184+
// list of plot methods to call (this list includes plot methods of 'gone' modules)
185+
var plotMethodsToCall = plotinfo.plotMethods || [];
186+
// list of plot methods of visible module on this subplot
187+
var plotMethods = [];
188+
var i, plotMethod;
189+
190+
for(i = 0; i < modules.length; i++) {
191+
var _module = modules[i];
192+
193+
if(_module.basePlotModule.name === 'cartesian') {
194+
plotMethod = _module.plot;
195+
Lib.pushUnique(plotMethodsToCall, plotMethod);
196+
Lib.pushUnique(plotMethods, plotMethod);
197+
}
193198
}
194199

195-
// plot all traces for each module at once
196-
for(var j = 0; j < modules.length; j++) {
197-
var _module = modules[j];
198-
199-
// skip over non-cartesian trace modules
200-
if(!_module.plot || _module.basePlotModule.name !== 'cartesian') continue;
200+
for(i = 0; i < plotMethodsToCall.length; i++) {
201+
plotMethod = plotMethodsToCall[i];
201202

202203
// plot all traces of this type on this subplot at once
203-
var cdModuleAndOthers = getModuleCalcData(cdSubplot, _module);
204+
var cdModuleAndOthers = getModuleCalcData(cdSubplot, plotMethod);
204205
var cdModule = cdModuleAndOthers[0];
205206
// don't need to search the found traces again - in fact we need to NOT
206207
// so that if two modules share the same plotter we don't double-plot
207208
cdSubplot = cdModuleAndOthers[1];
208209

209-
_module.plot(gd, plotinfo, cdModule, transitionOpts, makeOnCompleteCallback);
210+
plotMethod(gd, plotinfo, cdModule, transitionOpts, makeOnCompleteCallback);
210211
}
212+
213+
// save list of plot methods on subplot for later,
214+
// so that they can be called to clear traces of 'gone' modules
215+
plotinfo.plotMethods = plotMethods;
211216
}
212217

213218
exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) {
214-
var oldModules = oldFullLayout._modules || [];
215-
var newModules = newFullLayout._modules || [];
216219
var oldPlots = oldFullLayout._plots || {};
217-
218-
var hadScatter, hasScatter;
219-
var hadOHLC, hasOHLC;
220-
var hadGl, hasGl;
221-
var i, k, subplotInfo, moduleName;
220+
var newPlots = newFullLayout._plots || {};
221+
var oldSubplotList = oldFullLayout._subplots || {};
222+
var plotinfo;
223+
var i, k;
222224

223225
// when going from a large splom graph to something else,
224226
// we need to clear <g subplot> so that the new cartesian subplot
225227
// can have the correct layer ordering
226228
if(oldFullLayout._hasOnlyLargeSploms && !newFullLayout._hasOnlyLargeSploms) {
227229
for(k in oldPlots) {
228-
subplotInfo = oldPlots[k];
229-
if(subplotInfo.plotgroup) subplotInfo.plotgroup.remove();
230+
plotinfo = oldPlots[k];
231+
if(plotinfo.plotgroup) plotinfo.plotgroup.remove();
230232
}
231233
}
232234

233-
for(i = 0; i < oldModules.length; i++) {
234-
moduleName = oldModules[i].name;
235-
if(moduleName === 'scatter') hadScatter = true;
236-
else if(moduleName === 'scattergl') hadGl = true;
237-
else if(moduleName === 'ohlc') hadOHLC = true;
238-
}
239-
240-
for(i = 0; i < newModules.length; i++) {
241-
moduleName = newModules[i].name;
242-
if(moduleName === 'scatter') hasScatter = true;
243-
else if(moduleName === 'scattergl') hasGl = true;
244-
else if(moduleName === 'ohlc') hasOHLC = true;
245-
}
246-
247-
var layersToEmpty = [];
248-
if(hadScatter && !hasScatter) layersToEmpty.push('g.scatterlayer');
249-
if(hadOHLC && !hasOHLC) layersToEmpty.push('g.ohlclayer');
250-
251-
if(layersToEmpty.length) {
252-
for(var layeri = 0; layeri < layersToEmpty.length; layeri++) {
253-
for(k in oldPlots) {
254-
subplotInfo = oldPlots[k];
255-
if(subplotInfo.plot) {
256-
subplotInfo.plot.select(layersToEmpty[layeri])
257-
.selectAll('g.trace')
258-
.remove();
259-
}
260-
}
261-
262-
oldFullLayout._infolayer.selectAll('g.rangeslider-container')
263-
.select(layersToEmpty[layeri])
264-
.selectAll('g.trace')
265-
.remove();
266-
}
267-
}
235+
var hadGl = (oldFullLayout._has && oldFullLayout._has('gl'));
236+
var hasGl = (newFullLayout._has && newFullLayout._has('gl'));
268237

269238
if(hadGl && !hasGl) {
270239
for(k in oldPlots) {
271-
subplotInfo = oldPlots[k];
272-
273-
if(subplotInfo._scene) {
274-
subplotInfo._scene.destroy();
275-
}
240+
plotinfo = oldPlots[k];
241+
if(plotinfo._scene) plotinfo._scene.destroy();
276242
}
277243
}
278244

279-
var oldSubplotList = oldFullLayout._subplots || {};
280-
var newSubplotList = newFullLayout._subplots || {xaxis: [], yaxis: []};
281-
282245
// delete any titles we don't need anymore
283246
// check if axis list has changed, and if so clear old titles
284247
if(oldSubplotList.xaxis && oldSubplotList.yaxis) {

src/plots/get_data.js

+24-8
Original file line numberDiff line numberDiff line change
@@ -45,26 +45,42 @@ exports.getSubplotCalcData = function(calcData, type, subplotId) {
4545
* the calcdata we *will* plot with this module, and the ones we *won't*
4646
*
4747
* @param {array} calcdata: as in gd.calcdata
48-
* @param {object|string} typeOrModule: the plotting module, or its name
48+
* @param {object|string|fn} arg1:
49+
* the plotting module, or its name, or its plot method
4950
*
5051
* @return {array[array]} [foundCalcdata, remainingCalcdata]
5152
*/
52-
exports.getModuleCalcData = function(calcdata, typeOrModule) {
53+
exports.getModuleCalcData = function(calcdata, arg1) {
5354
var moduleCalcData = [];
5455
var remainingCalcData = [];
55-
var _module = typeof typeOrModule === 'string' ? Registry.getModule(typeOrModule) : typeOrModule;
56-
if(!_module) return [moduleCalcData, calcdata];
56+
57+
var plotMethod;
58+
if(arg1) {
59+
var typeOfArg1 = typeof arg1;
60+
if(typeOfArg1 === 'string') {
61+
plotMethod = Registry.getModule(arg1).plot;
62+
} else if(typeOfArg1 === 'function') {
63+
plotMethod = arg1;
64+
} else {
65+
plotMethod = arg1.plot;
66+
}
67+
}
68+
if(!plotMethod) {
69+
return [moduleCalcData, calcdata];
70+
}
5771

5872
for(var i = 0; i < calcdata.length; i++) {
5973
var cd = calcdata[i];
6074
var trace = cd[0].trace;
6175
if(trace.visible !== true) continue;
6276

63-
// we use this to find data to plot - so if there's a .plot
64-
if(trace._module.plot === _module.plot) {
77+
// group calcdata trace not by 'module' (as the name of this function
78+
// would suggest), but by 'module plot method' so that if some traces
79+
// share the same module plot method (e.g. bar and histogram), we
80+
// only call it one!
81+
if(trace._module.plot === plotMethod) {
6582
moduleCalcData.push(cd);
66-
}
67-
else {
83+
} else {
6884
remainingCalcData.push(cd);
6985
}
7086
}

0 commit comments

Comments
 (0)