Skip to content

Axis constraints #1522

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 16 commits into from
Apr 3, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
push final constraint management into relayout so it always works
  • Loading branch information
alexcjohnson committed Mar 29, 2017
commit f521227fd25a31d158268355f610debf624c67dd
46 changes: 40 additions & 6 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var helpers = require('./helpers');
var subroutines = require('./subroutines');
var cartesianConstants = require('../plots/cartesian/constants');
var enforceAxisConstraints = require('../plots/cartesian/constraints');
var axisIds = require('../plots/cartesian/axis_ids');


/**
Expand Down Expand Up @@ -1860,6 +1861,16 @@ function _relayout(gd, aobj) {
return (ax || {}).autorange;
}

// for constraint enforcement: keep track of all axes (as {id: name})
// we're editing the (auto)range of, so we can tell the others constrained
// to scale with them that it's OK for them to shrink
var rangesAltered = {};

function recordAlteredAxis(pleafPlus) {
var axId = axisIds.name2id(pleafPlus.split('.')[0]);
rangesAltered[axId] = 1;
}

// alter gd.layout
for(var ai in aobj) {
if(helpers.hasParent(aobj, ai)) {
Expand Down Expand Up @@ -1894,15 +1905,17 @@ function _relayout(gd, aobj) {
//
// To do so, we must manually set them back here using the _initialAutoSize cache.
if(['width', 'height'].indexOf(ai) !== -1 && vi === null) {
gd._fullLayout[ai] = gd._initialAutoSize[ai];
fullLayout[ai] = gd._initialAutoSize[ai];
}
// check autorange vs range
else if(pleafPlus.match(/^[xyz]axis[0-9]*\.range(\[[0|1]\])?$/)) {
doextra(ptrunk + '.autorange', false);
recordAlteredAxis(pleafPlus);
}
else if(pleafPlus.match(/^[xyz]axis[0-9]*\.autorange$/)) {
doextra([ptrunk + '.range[0]', ptrunk + '.range[1]'],
undefined);
recordAlteredAxis(pleafPlus);
}
else if(pleafPlus.match(/^aspectratio\.[xyz]$/)) {
doextra(proot + '.aspectmode', 'manual');
Expand Down Expand Up @@ -2121,16 +2134,37 @@ function _relayout(gd, aobj) {
if(!finished) flags.doplot = true;
}

var oldWidth = gd._fullLayout.width,
oldHeight = gd._fullLayout.height;
// figure out if we need to recalculate axis constraints
var constraints = fullLayout._axisConstraintGroups;
for(var axId in rangesAltered) {
for(i = 0; i < constraints.length; i++) {
var group = constraints[i];
if(group[axId]) {
// Always recalc if we're changing constrained ranges.
// Otherwise it's possible to violate the constraints by
// specifying arbitrary ranges for all axes in the group.
// this way some ranges may expand beyond what's specified,
// as they do at first draw, to satisfy the constraints.
flags.docalc = true;
for(var groupAxId in group) {
if(!rangesAltered[groupAxId]) {
axisIds.getFromId(gd, groupAxId)._constraintShrinkable = true;
}
}
}
}
}

var oldWidth = fullLayout.width,
oldHeight = fullLayout.height;

// calculate autosizing
if(gd.layout.autosize) Plots.plotAutoSize(gd, gd.layout, gd._fullLayout);
if(gd.layout.autosize) Plots.plotAutoSize(gd, gd.layout, fullLayout);

// avoid unnecessary redraws
var hasSizechanged = aobj.height || aobj.width ||
(gd._fullLayout.width !== oldWidth) ||
(gd._fullLayout.height !== oldHeight);
(fullLayout.width !== oldWidth) ||
(fullLayout.height !== oldHeight);

if(hasSizechanged) flags.docalc = true;

Expand Down
36 changes: 13 additions & 23 deletions src/plots/cartesian/dragbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -567,15 +567,8 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) {

var doubleClickConfig = gd._context.doubleClick,
axList = (xActive ? xa : []).concat(yActive ? ya : []),
linkedAxList = (xActive || isSubplotConstrained ? xaLinked : [])
.concat(yActive ? yaLinked : []),
attrs = {};

if(isSubplotConstrained) {
if(!xActive) linkedAxList = linkedAxList.concat(xa);
else if(!yActive) linkedAxList = linkedAxList.concat(ya);
}

var ax, i, rangeInitial;

// For reset+autosize mode:
Expand All @@ -602,14 +595,8 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) {
}

if(doubleClickConfig === 'autosize') {
// when we're autosizing one or a few axes, mark the other axes as
// "shrinkable" so that we don't expand to cover whatever their
// current ranges might be, but instead we just autosize to the
// selected axes
for(i = 0; i < linkedAxList.length; i++) {
linkedAxList[i]._constraintShrinkable = true;
}

// don't set the linked axes here, so relayout marks them as shrinkable
// and we autosize just to the requested axis/axes
for(i = 0; i < axList.length; i++) {
ax = axList[i];
if(!ax.fixedrange) attrs[ax._name + '.autorange'] = true;
Expand All @@ -618,7 +605,13 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) {
else if(doubleClickConfig === 'reset') {
// when we're resetting, reset all linked axes too, so we get back
// to the fully-auto-with-constraints situation
axList = axList.concat(linkedAxList);
if(xActive || isSubplotConstrained) axList = axList.concat(xaLinked);
if(yActive && !isSubplotConstrained) axList = axList.concat(yaLinked);

if(isSubplotConstrained) {
if(!xActive) axList = axList.concat(xa);
else if(!yActive) axList = axList.concat(ya);
}

for(i = 0; i < axList.length; i++) {
ax = axList[i];
Expand All @@ -645,13 +638,10 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) {
var attrs = {};
// revert to the previous axis settings, then apply the new ones
// through relayout - this lets relayout manage undo/redo
var axesToModify = [];
if(zoommode === 'x' || zoommode === 'xy') {
axesToModify = xa.concat(xaLinked);
}
if(zoommode === 'y' || zoommode === 'xy') {
axesToModify = axesToModify.concat(ya, yaLinked);
}
var axesToModify;
if(zoommode === 'xy') axesToModify = xa.concat(ya);
else if(zoommode === 'x') axesToModify = xa;
else if(zoommode === 'y') axesToModify = ya;

for(var i = 0; i < axesToModify.length; i++) {
var axi = axesToModify[i];
Expand Down