Skip to content
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

Layout grids #2399

Merged
merged 12 commits into from
Feb 26, 2018
19 changes: 11 additions & 8 deletions src/lib/regex.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@

'use strict';

// Simple helper functions
// none of these need any external deps

/*
* make a regex for matching counter ids/names ie xaxis, xaxis2, xaxis10...
* eg: regexCounter('x')
* tail is an optional piece after the id
* eg regexCounter('scene', '.annotations') for scene2.annotations etc.
*
* @param {string} head: the head of the pattern, eg 'x' matches 'x', 'x2', 'x10' etc.
* 'xy' is a special case for cartesian subplots: it matches 'x2y3' etc
* @param {Optional(string)} tail: a fixed piece after the id
* eg counterRegex('scene', '.annotations') for scene2.annotations etc.
* @param {boolean} openEnded: if true, the string may continue past the match.
*/
exports.counter = function(head, tail, openEnded) {
return new RegExp('^' + head + '([2-9]|[1-9][0-9]+)?' +
(tail || '') + (openEnded ? '' : '$'));
var fullTail = (tail || '') + (openEnded ? '' : '$');
if(head === 'xy') {
return new RegExp('^x([2-9]|[1-9][0-9]+)?y([2-9]|[1-9][0-9]+)?' + fullTail);
}
return new RegExp('^' + head + '([2-9]|[1-9][0-9]+)?' + fullTail);
};
2 changes: 1 addition & 1 deletion src/plots/cartesian/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

'use strict';
var counterRegex = require('../../lib').counterRegex;
var counterRegex = require('../../lib/regex').counter;


module.exports = {
Expand Down
3 changes: 2 additions & 1 deletion src/plots/cartesian/layout_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
var positioningOptions = {
letter: axLetter,
counterAxes: counterAxes[axLetter],
overlayableAxes: overlayableAxes
overlayableAxes: overlayableAxes,
grid: layoutOut.grid
};

handlePositionDefaults(axLayoutIn, axLayoutOut, coerce, positioningOptions);
Expand Down
37 changes: 27 additions & 10 deletions src/plots/cartesian/position_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,43 @@ var Lib = require('../../lib');


module.exports = function handlePositionDefaults(containerIn, containerOut, coerce, options) {
var counterAxes = options.counterAxes || [],
overlayableAxes = options.overlayableAxes || [],
letter = options.letter;
var counterAxes = options.counterAxes || [];
var overlayableAxes = options.overlayableAxes || [];
var letter = options.letter;
var grid = options.grid;

var dfltAnchor, dfltDomain, dfltSide, dfltPosition;

if(grid) {
dfltDomain = grid._domains[letter][grid._axisMap[containerOut._id]];
dfltAnchor = grid._anchors[containerOut._id];
if(dfltDomain) {
dfltSide = grid[letter + 'side'].split(' ')[0];
dfltPosition = grid.domain[letter][dfltSide === 'right' || dfltSide === 'top' ? 1 : 0];
}
}

// Even if there's a grid, this axis may not be in it - fall back on non-grid defaults
dfltDomain = dfltDomain || [0, 1];
dfltAnchor = dfltAnchor || (isNumeric(containerIn.position) ? 'free' : (counterAxes[0] || 'free'));
dfltSide = dfltSide || (letter === 'x' ? 'bottom' : 'left');
dfltPosition = dfltPosition || 0;

var anchor = Lib.coerce(containerIn, containerOut, {
anchor: {
valType: 'enumerated',
values: ['free'].concat(counterAxes),
dflt: isNumeric(containerIn.position) ? 'free' :
(counterAxes[0] || 'free')
dflt: dfltAnchor
}
}, 'anchor');

if(anchor === 'free') coerce('position');
if(anchor === 'free') coerce('position', dfltPosition);

Lib.coerce(containerIn, containerOut, {
side: {
valType: 'enumerated',
values: letter === 'x' ? ['bottom', 'top'] : ['left', 'right'],
dflt: letter === 'x' ? 'bottom' : 'left'
dflt: dfltSide
}
}, 'side');

Expand All @@ -54,9 +71,9 @@ module.exports = function handlePositionDefaults(containerIn, containerOut, coer
// in ax.setscale()... but this means we still need (imperfect) logic
// in the axes popover to hide domain for the overlaying axis.
// perhaps I should make a private version _domain that all axes get???
var domain = coerce('domain');
if(domain[0] > domain[1] - 0.01) containerOut.domain = [0, 1];
Lib.noneOrAll(containerIn.domain, containerOut.domain, [0, 1]);
var domain = coerce('domain', dfltDomain);
if(domain[0] > domain[1] - 0.01) containerOut.domain = dfltDomain;
Lib.noneOrAll(containerIn.domain, containerOut.domain, dfltDomain);
}

coerce('layer');
Expand Down
62 changes: 60 additions & 2 deletions src/plots/domain_attributes.js → src/plots/domain.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ var extendFlat = require('../lib/extend').extendFlat;
* opts.trace: set to true for trace containers
* @param {string}
* opts.editType: editType for all pieces
* @param {boolean}
* opts.noGridCell: set to true to omit `row` and `column`
*
* @param {object} extra
* @param {string}
Expand All @@ -29,7 +31,7 @@ var extendFlat = require('../lib/extend').extendFlat;
*
* @return {object} attributes object containing {x,y} as specified
*/
module.exports = function(opts, extra) {
exports.attributes = function(opts, extra) {
opts = opts || {};
extra = extra || {};

Expand All @@ -48,7 +50,7 @@ module.exports = function(opts, extra) {
var contPart = opts.trace ? 'trace ' : 'subplot ';
var descPart = extra.description ? ' ' + extra.description : '';

return {
var out = {
x: extendFlat({}, base, {
description: [
'Sets the horizontal domain of this ',
Expand All @@ -69,4 +71,60 @@ module.exports = function(opts, extra) {
}),
editType: opts.editType
};

if(!opts.noGridCell) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see any noGridCell options being set. 🔪 ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

noGridCell shows up in the domain for the grid itself - you can't put the grid in itself! 😄

out.row = {
valType: 'integer',
min: 0,
Copy link
Contributor

Choose a reason for hiding this comment

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

Two suggestions:

  • It might be worth adding a dflt: 0, so that domain: {column: 2} defaults to subplot xy2?
  • It might be nice to allow domain: {row: ''} to match the 'x'/'x2'/'x3' counter

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It might be worth adding a dflt: 0, so that domain: {column: 2} defaults to subplot xy2?

Yeah, makes sense - if you have a grid, by default all subplots should go in it. You can always set explicit domain.x and domain.y anyhow, this is only setting the defaults for those attributes -> 4b43e35

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It might be nice to allow domain: {row: ''} to match the 'x'/'x2'/'x3' counter

As discussed offline, I omitted this one (though if you say '' you'll get 0 now anyway with the change ^^ so the result is the same)

role: 'info',
editType: opts.editType,
description: [
'If there is a layout grid, use the domain ',
'for this row in the grid for this ',
namePart,
contPart,
'.',
descPart
].join('')
};
out.column = {
valType: 'integer',
min: 0,
role: 'info',
editType: opts.editType,
description: [
'If there is a layout grid, use the domain ',
'for this column in the grid for this ',
namePart,
contPart,
'.',
descPart
].join('')
};
}

return out;
};

exports.defaults = function(containerOut, layout, coerce, dfltDomains) {
var dfltX = (dfltDomains && dfltDomains.x) || [0, 1];
var dfltY = (dfltDomains && dfltDomains.y) || [0, 1];

var grid = layout.grid;
if(grid) {
var column = coerce('domain.column');
if(column !== undefined) {
if(column < grid.columns) dfltX = grid._domains.x[column];
else delete containerOut.domain.column;
}

var row = coerce('domain.row');
if(row !== undefined) {
if(row < grid.rows) dfltY = grid._domains.y[row];
else delete containerOut.domain.row;
}
}

coerce('domain.x', dfltX);
coerce('domain.y', dfltY);
};
2 changes: 1 addition & 1 deletion src/plots/geo/layout/layout_attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
'use strict';

var colorAttrs = require('../../../components/color/attributes');
var domainAttrs = require('../../domain_attributes');
var domainAttrs = require('../../domain').attributes;
var constants = require('../constants');
var overrideAll = require('../../../plot_api/edit_types').overrideAll;

Expand Down
2 changes: 1 addition & 1 deletion src/plots/gl3d/layout/layout_attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
'use strict';

var gl3dAxisAttrs = require('./axis_attributes');
var domainAttrs = require('../../domain_attributes');
var domainAttrs = require('../../domain').attributes;
var extendFlat = require('../../../lib/extend').extendFlat;
var counterRegex = require('../../../lib').counterRegex;

Expand Down
Loading