Skip to content

Clean up automargin pipeline a bit #3323

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Dec 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/legend/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
coerce('orientation');
if(containerOut.orientation === 'h') {
var xaxis = layoutIn.xaxis;
if(xaxis && xaxis.rangeslider && xaxis.rangeslider.visible) {
if(Registry.getComponentMethod('rangeslider', 'isVisible')(xaxis)) {
defaultX = 0;
defaultXAnchor = 'left';
defaultY = 1.1;
Expand Down
78 changes: 25 additions & 53 deletions src/components/rangeslider/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,21 @@ var Color = require('../color');
var Titles = require('../titles');

var Cartesian = require('../../plots/cartesian');
var Axes = require('../../plots/cartesian/axes');
var axisIDs = require('../../plots/cartesian/axis_ids');

var dragElement = require('../dragelement');
var setCursor = require('../../lib/setcursor');

var constants = require('./constants');

module.exports = function(gd) {
var fullLayout = gd._fullLayout,
rangeSliderData = makeRangeSliderData(fullLayout);
var fullLayout = gd._fullLayout;
var rangeSliderData = fullLayout._rangeSliderData;
for(var i = 0; i < rangeSliderData.length; i++) {
var opts = rangeSliderData[i][constants.name];
// fullLayout._uid may not exist when we call makeData
opts._clipId = opts._id + '-' + fullLayout._uid;
}

/*
* <g container />
Expand All @@ -55,10 +60,6 @@ module.exports = function(gd) {
.selectAll('g.' + constants.containerClassName)
.data(rangeSliderData, keyFunction);

rangeSliders.enter().append('g')
.classed(constants.containerClassName, true)
.attr('pointer-events', 'all');

// remove exiting sliders and their corresponding clip paths
rangeSliders.exit().each(function(axisOpts) {
var opts = axisOpts[constants.name];
Expand All @@ -68,12 +69,16 @@ module.exports = function(gd) {
// return early if no range slider is visible
if(rangeSliderData.length === 0) return;

rangeSliders.enter().append('g')
.classed(constants.containerClassName, true)
.attr('pointer-events', 'all');

// for all present range sliders
rangeSliders.each(function(axisOpts) {
var rangeSlider = d3.select(this),
opts = axisOpts[constants.name],
oppAxisOpts = fullLayout[Axes.id2name(axisOpts.anchor)],
oppAxisRangeOpts = opts[Axes.id2name(axisOpts.anchor)];
var rangeSlider = d3.select(this);
var opts = axisOpts[constants.name];
var oppAxisOpts = fullLayout[axisIDs.id2name(axisOpts.anchor)];
var oppAxisRangeOpts = opts[axisIDs.id2name(axisOpts.anchor)];

// update range
// Expand slider range to the axis range
Expand All @@ -97,19 +102,9 @@ module.exports = function(gd) {
var domain = axisOpts.domain;
var tickHeight = (axisOpts._boundingBox || {}).height || 0;

var oppBottom = Infinity;
var subplotData = Axes.getSubplots(gd, axisOpts);
for(var i = 0; i < subplotData.length; i++) {
var oppAxis = Axes.getFromId(gd, subplotData[i].substr(subplotData[i].indexOf('y')));
oppBottom = Math.min(oppBottom, oppAxis.domain[0]);
}

opts._id = constants.name + axisOpts._id;
opts._clipId = opts._id + '-' + fullLayout._uid;
var oppBottom = opts._oppBottom;

opts._width = graphSize.w * (domain[1] - domain[0]);
opts._height = (fullLayout.height - margin.b - margin.t) * opts.thickness;
opts._offsetShift = Math.floor(opts.borderwidth / 2);

var x = Math.round(margin.l + (graphSize.w * domain[0]));

Expand Down Expand Up @@ -177,36 +172,9 @@ module.exports = function(gd) {
}
});
}

// update margins
Plots.autoMargin(gd, opts._id, {
x: domain[0],
y: oppBottom,
l: 0,
r: 0,
t: 0,
b: opts._height + margin.b + tickHeight,
pad: constants.extraPad + opts._offsetShift * 2
});
});
};

function makeRangeSliderData(fullLayout) {
var axes = Axes.list({ _fullLayout: fullLayout }, 'x', true),
name = constants.name,
out = [];

if(fullLayout._has('gl2d')) return out;

for(var i = 0; i < axes.length; i++) {
var ax = axes[i];

if(ax[name] && ax[name].visible) out.push(ax);
}

return out;
}

function setupDragElement(rangeSlider, gd, axisOpts, opts) {
var slideBox = rangeSlider.select('rect.' + constants.slideBoxClassName).node(),
grabAreaMin = rangeSlider.select('rect.' + constants.grabAreaMinClassName).node(),
Expand Down Expand Up @@ -393,11 +361,10 @@ function addClipPath(rangeSlider, gd, axisOpts, opts) {
}

function drawRangePlot(rangeSlider, gd, axisOpts, opts) {
var subplotData = Axes.getSubplots(gd, axisOpts),
calcData = gd.calcdata;
var calcData = gd.calcdata;

var rangePlots = rangeSlider.selectAll('g.' + constants.rangePlotClassName)
.data(subplotData, Lib.identity);
.data(axisOpts._subplotsWith, Lib.identity);

rangePlots.enter().append('g')
.attr('class', function(id) { return constants.rangePlotClassName + ' ' + id; })
Expand All @@ -413,7 +380,7 @@ function drawRangePlot(rangeSlider, gd, axisOpts, opts) {
var plotgroup = d3.select(this),
isMainPlot = (i === 0);

var oppAxisOpts = Axes.getFromId(gd, id, 'y'),
var oppAxisOpts = axisIDs.getFromId(gd, id, 'y'),
oppAxisName = oppAxisOpts._name,
oppAxisRangeOpts = opts[oppAxisName];

Expand Down Expand Up @@ -445,6 +412,11 @@ function drawRangePlot(rangeSlider, gd, axisOpts, opts) {
var xa = mockFigure._fullLayout.xaxis;
var ya = mockFigure._fullLayout[oppAxisName];

xa.clearCalc();
xa.setScale();
ya.clearCalc();
ya.setScale();

var plotinfo = {
id: id,
plotgroup: plotgroup,
Expand Down
67 changes: 67 additions & 0 deletions src/components/rangeslider/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var axisIDs = require('../../plots/cartesian/axis_ids');
var constants = require('./constants');
var name = constants.name;

function isVisible(ax) {
var rangeSlider = ax && ax[name];
return rangeSlider && rangeSlider.visible;
}
exports.isVisible = isVisible;

exports.makeData = function(fullLayout) {
var axes = axisIDs.list({ _fullLayout: fullLayout }, 'x', true);
var margin = fullLayout.margin;
var rangeSliderData = [];

if(!fullLayout._has('gl2d')) {
for(var i = 0; i < axes.length; i++) {
var ax = axes[i];

if(isVisible(ax)) {
rangeSliderData.push(ax);

var opts = ax[name];
opts._id = name + ax._id;
opts._height = (fullLayout.height - margin.b - margin.t) * opts.thickness;
opts._offsetShift = Math.floor(opts.borderwidth / 2);
}
}
}

fullLayout._rangeSliderData = rangeSliderData;
};

exports.autoMarginOpts = function(gd, ax) {
var opts = ax[name];

var oppBottom = Infinity;
var counterAxes = ax._counterAxes;
for(var j = 0; j < counterAxes.length; j++) {
var counterId = counterAxes[j];
var oppAxis = axisIDs.getFromId(gd, counterId);
oppBottom = Math.min(oppBottom, oppAxis.domain[0]);
}
opts._oppBottom = oppBottom;

var tickHeight = (ax.side === 'bottom' && ax._boundingBox.height) || 0;

return {
x: 0,
y: oppBottom,
l: 0,
r: 0,
t: 0,
b: opts._height + gd._fullLayout.margin.b + tickHeight,
pad: constants.extraPad + opts._offsetShift * 2
};
};
6 changes: 5 additions & 1 deletion src/components/rangeslider/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
var Lib = require('../../lib');
var attrs = require('./attributes');
var oppAxisAttrs = require('./oppaxis_attributes');
var helpers = require('./helpers');

module.exports = {
moduleType: 'component',
Expand All @@ -29,5 +30,8 @@ module.exports = {
layoutAttributes: require('./attributes'),
handleDefaults: require('./defaults'),
calcAutorange: require('./calc_autorange'),
draw: require('./draw')
draw: require('./draw'),
isVisible: helpers.isVisible,
makeData: helpers.makeData,
autoMarginOpts: helpers.autoMarginOpts
};
8 changes: 6 additions & 2 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,7 @@ exports.plot = function(gd, data, layout, config) {
return Lib.syncOrAsync([
Registry.getComponentMethod('shapes', 'calcAutorange'),
Registry.getComponentMethod('annotations', 'calcAutorange'),
doAutoRangeAndConstraints,
Registry.getComponentMethod('rangeslider', 'calcAutorange')
doAutoRangeAndConstraints
], gd);
}

Expand All @@ -345,6 +344,11 @@ exports.plot = function(gd, data, layout, config) {
// store initial ranges *after* enforcing constraints, otherwise
// we will never look like we're at the initial ranges
if(graphWasEmpty) Axes.saveRangeInitial(gd);

// this one is different from shapes/annotations calcAutorange
// the others incorporate those components into ax._extremes,
// this one actually sets the ranges in rangesliders.
Registry.getComponentMethod('rangeslider', 'calcAutorange')(gd);
}

// draw ticks, titles, and calculate axis scaling (._b, ._m)
Expand Down
56 changes: 4 additions & 52 deletions src/plot_api/subroutines.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function lsInner(gd) {
var gs = fullLayout._size;
var pad = gs.p;
var axList = Axes.list(gd, '', true);
var i, subplot, plotinfo, xa, ya;
var i, subplot, plotinfo, ax, xa, ya;

fullLayout._paperdiv.style({
width: (gd._context.responsive && fullLayout.autosize && !gd._context._hasZeroWidth && !gd.layout.width) ? '100%' : fullLayout.width + 'px',
Expand Down Expand Up @@ -91,10 +91,7 @@ function lsInner(gd) {

// some preparation of axis position info
for(i = 0; i < axList.length; i++) {
var ax = axList[i];

// reset scale in case the margins have changed
ax.setScale();
ax = axList[i];

var counterAx = ax._anchorAxis;

Expand All @@ -113,11 +110,6 @@ function lsInner(gd) {
ax._mainMirrorPosition = (ax.mirror && counterAx) ?
getLinePosition(ax, counterAx,
alignmentConstants.OPPOSITE_SIDE[ax.side]) : null;

// Figure out which subplot to draw ticks, labels, & axis lines on
// do this as a separate loop so we already have all the
// _mainAxis and _anchorAxis links set
ax._mainSubplot = findMainSubplot(ax, fullLayout);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved this into plots.linkSubplots, which is both a more obvious place for it and happens earlier (in supplyDefaults) so _mainSubplot is available sooner.

}

// figure out which backgrounds we need to draw,
Expand Down Expand Up @@ -358,48 +350,6 @@ function lsInner(gd) {
return gd._promises.length && Promise.all(gd._promises);
}

function findMainSubplot(ax, fullLayout) {
var subplotList = fullLayout._subplots;
var ids = subplotList.cartesian.concat(subplotList.gl2d || []);
var mockGd = {_fullLayout: fullLayout};

var isX = ax._id.charAt(0) === 'x';
var anchorAx = ax._mainAxis._anchorAxis;
var mainSubplotID = '';
var nextBestMainSubplotID = '';
var anchorID = '';

// First try the main ID with the anchor
if(anchorAx) {
anchorID = anchorAx._mainAxis._id;
mainSubplotID = isX ? (ax._id + anchorID) : (anchorID + ax._id);
}

// Then look for a subplot with the counteraxis overlaying the anchor
// If that fails just use the first subplot including this axis
if(!mainSubplotID || !fullLayout._plots[mainSubplotID]) {
mainSubplotID = '';

for(var j = 0; j < ids.length; j++) {
var id = ids[j];
var yIndex = id.indexOf('y');
var idPart = isX ? id.substr(0, yIndex) : id.substr(yIndex);
var counterPart = isX ? id.substr(yIndex) : id.substr(0, yIndex);

if(idPart === ax._id) {
if(!nextBestMainSubplotID) nextBestMainSubplotID = id;
var counterAx = Axes.getFromId(mockGd, counterPart);
if(anchorID && counterAx.overlaying === anchorID) {
mainSubplotID = id;
break;
}
}
}
}

return mainSubplotID || nextBestMainSubplotID;
}

function shouldShowLinesOrTicks(ax, subplot) {
return (ax.ticks || ax.showline) &&
(subplot === ax._mainSubplot || ax.mirror === 'all' || ax.mirror === 'allticks');
Expand Down Expand Up @@ -752,6 +702,8 @@ exports.doAutoRangeAndConstraints = function(gd) {
for(var i = 0; i < axList.length; i++) {
var ax = axList[i];
cleanAxisConstraints(gd, ax);
// in case margins changed, update scale
ax.setScale();
doAutoRange(gd, ax);
}

Expand Down
15 changes: 6 additions & 9 deletions src/plots/cartesian/autorange.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,6 @@ function concatExtremes(gd, ax) {
}

function doAutoRange(gd, ax) {
if(!ax._length) ax.setScale();

var axIn;

if(ax.autorange) {
ax.range = getAutoRange(gd, ax);

Expand All @@ -250,7 +246,7 @@ function doAutoRange(gd, ax) {
// doAutoRange will get called on fullLayout,
// but we want to report its results back to layout

axIn = ax._input;
var axIn = ax._input;

// before we edit _input, store preGUI values
var edits = {};
Expand All @@ -262,15 +258,16 @@ function doAutoRange(gd, ax) {
axIn.autorange = ax.autorange;
}

if(ax._anchorAxis && ax._anchorAxis.rangeslider) {
var axeRangeOpts = ax._anchorAxis.rangeslider[ax._name];
var anchorAx = ax._anchorAxis;

if(anchorAx && anchorAx.rangeslider) {
var axeRangeOpts = anchorAx.rangeslider[ax._name];
if(axeRangeOpts) {
if(axeRangeOpts.rangemode === 'auto') {
axeRangeOpts.range = getAutoRange(gd, ax);
}
}
axIn = ax._anchorAxis._input;
axIn.rangeslider[ax._name] = Lib.extendFlat({}, axeRangeOpts);
anchorAx._input.rangeslider[ax._name] = Lib.extendFlat({}, axeRangeOpts);
}
}

Expand Down
Loading