Skip to content

Commit

Permalink
image: layout defaults: add scaleanchor, fix logic for reverse axis
Browse files Browse the repository at this point in the history
  • Loading branch information
antoinerg committed Oct 25, 2019
1 parent c8a9f8a commit 5c42db8
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 18 deletions.
8 changes: 5 additions & 3 deletions src/plots/cartesian/constraints.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ var concatExtremes = require('./autorange').concatExtremes;
var ALMOST_EQUAL = require('../../constants/numerical').ALMOST_EQUAL;
var FROM_BL = require('../../constants/alignment').FROM_BL;

exports.handleConstraintDefaults = function(containerIn, containerOut, coerce, allAxisIds, layoutOut) {
exports.handleConstraintDefaults = function(containerIn, containerOut, coerce, opts) {
var allAxisIds = opts.allAxisIds;
var layoutOut = opts.layoutOut;
var constraintGroups = layoutOut._axisConstraintGroups;
var matchGroups = layoutOut._axisMatchGroups;
var axId = containerOut._id;
Expand Down Expand Up @@ -53,14 +55,14 @@ exports.handleConstraintDefaults = function(containerIn, containerOut, coerce, a
// 'matches' wins over 'scaleanchor' (for now)
var scaleanchor, scaleOpts;

if(!matches && containerIn.scaleanchor && !(containerOut.fixedrange && constrain !== 'domain')) {
if(!matches && (containerIn.scaleanchor || opts.scaleanchorDflt) && !(containerOut.fixedrange && constrain !== 'domain')) {
scaleOpts = getConstraintOpts(constraintGroups, thisID, allAxisIds, layoutOut, constrain);
scaleanchor = Lib.coerce(containerIn, containerOut, {
scaleanchor: {
valType: 'enumerated',
values: scaleOpts.linkableAxes || []
}
}, 'scaleanchor');
}, 'scaleanchor', opts.scaleanchorDflt);
}

if(matches) {
Expand Down
32 changes: 21 additions & 11 deletions src/plots/cartesian/layout_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
var yaMayHide = {};
var xaMustDisplay = {};
var yaMustDisplay = {};
var yaMustForward = {};
var yaMayBackward = {};
var yaMustNotReverse = {};
var yaMayReverse = {};
var yaMustNotScaleanchor = {};
var yaMayScaleanchor = {};
var outerTicks = {};
var noGrids = {};
var i, j;
Expand Down Expand Up @@ -74,24 +76,24 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
if(trace.type === 'funnel') {
if(trace.orientation === 'h') {
if(xaName) xaMayHide[xaName] = true;
if(yaName) yaMayBackward[yaName] = true;
if(yaName) yaMayReverse[yaName] = true;
} else {
if(yaName) yaMayHide[yaName] = true;
}
yaMustNotScaleanchor[yaName] = true;
} else if(trace.type === 'image') {
if(yaName) yaMayReverse[yaName] = true;
if(yaName) yaMayScaleanchor[yaName] = true;
} else {
if(yaName) {
yaMustDisplay[yaName] = true;
yaMustForward[yaName] = true;
yaMustNotReverse[yaName] = true;
yaMustNotScaleanchor[yaName] = true;
}

if(!traceIs(trace, 'carpet') || (trace.type === 'carpet' && !trace._cheater)) {
if(xaName) xaMustDisplay[xaName] = true;
}

if(trace.type === 'image') {
if(yaName) yaMustForward[yaName] = false;
if(yaName) yaMayBackward[yaName] = true;
}
}

// Two things trigger axis visibility:
Expand Down Expand Up @@ -197,7 +199,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
(axLetter === 'y' && !yaMustDisplay[axName] && yaMayHide[axName]);

var reverseDflt =
(axLetter === 'y' && !yaMustForward[axName] && yaMayBackward[axName]);
(axLetter === 'y' && !yaMustNotReverse[axName] && yaMayReverse[axName]);

var defaultOptions = {
letter: axLetter,
Expand Down Expand Up @@ -299,7 +301,15 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
axLayoutIn = layoutIn[axName];
axLayoutOut = layoutOut[axName];

handleConstraintDefaults(axLayoutIn, axLayoutOut, coerce, allAxisIds, layoutOut);
var scaleanchorDflt = null;
if(axLetter === 'y' && !axLayoutIn.hasOwnProperty('scaleanchor') && !yaMustNotScaleanchor[axName] && yaMayScaleanchor[axName]) {
scaleanchorDflt = axLayoutOut.anchor;
}
handleConstraintDefaults(axLayoutIn, axLayoutOut, coerce, {
allAxisIds: allAxisIds,
layoutOut: layoutOut,
scaleanchorDflt: scaleanchorDflt
});
}

for(i = 0; i < matchGroups.length; i++) {
Expand Down
Binary file modified test/image/baselines/image_axis_reverse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/image_axis_type.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion test/image/mocks/image_adventurer.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion test/image/mocks/image_axis_type.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"width": 400, "height": 600, "title": {"text": "Image on categorical and log axes"},
"grid": {"rows": 2, "columns": 1, "pattern": "independent"},
"xaxis2": {"type": "log"},
"yaxis2": {"type": "log"}
"yaxis": {"scaleanchor": null},
"yaxis2": {"type": "log", "scaleanchor": null}
}
}
2 changes: 1 addition & 1 deletion test/image/mocks/image_cat.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"layout": {
"width": 400, "height": 400, "yaxis": {"scaleanchor": "x"}, "margin": {"t":25, "b": 25, "r": 25, "l": 40}
"width": 400, "height": 400, "yaxis": {"scaleanchor": "x", "autorange": "reversed"}, "margin": {"t":25, "b": 25, "r": 25, "l": 40}
},
"data": [
{"x":[50, 150, 350, 50], "y":[350, 23, 100, 350]},
Expand Down
2 changes: 2 additions & 0 deletions test/image/mocks/image_colormodel.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
}],
"layout": {
"grid": {"rows": 2, "columns": 1, "pattern": "independent"},
"yaxis": {"scaleanchor": null},
"yaxis2": {"scaleanchor": null},
"width": 600,
"height": 400
}
Expand Down
1 change: 1 addition & 0 deletions test/image/mocks/image_opacity.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"z": [[[255, 0, 0], [0, 255, 0], [0, 0, 255]]]
}],
"layout": {
"yaxis": {"scaleanchor": null},
"width": 400, "height": 400,
"title": {
"text": "image with opacity 0.1"
Expand Down
1 change: 1 addition & 0 deletions test/image/mocks/image_with_gaps.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"zmax": [1, 1, 1]
}],
"layout": {
"yaxis": {"scaleanchor": null},
"width": 400, "height": 400, "title": {"text": "Image with missing pixels"}
}
}
8 changes: 8 additions & 0 deletions test/image/mocks/image_zmin_zmax.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@
"layout": {
"width": 400,
"height": 800,
"yaxis": {"scaleanchor": null},
"yaxis2": {"scaleanchor": null},
"yaxis3": {"scaleanchor": null},
"yaxis4": {"scaleanchor": null},
"yaxis5": {"scaleanchor": null},
"yaxis6": {"scaleanchor": null},
"yaxis7": {"scaleanchor": null},
"yaxis8": {"scaleanchor": null},
"grid": {
"rows": 4,
"columns": 2,
Expand Down
58 changes: 57 additions & 1 deletion test/jasmine/tests/image_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,62 @@ describe('image supplyDefaults', function() {
});
});

describe('image smart layout defaults', function() {
var gd;
beforeEach(function() {
gd = createGraphDiv();
});

afterEach(destroyGraphDiv);

it('should reverse yaxis if only images are present', function(done) {
Plotly.newPlot(gd, [{type: 'image', z: [[[255, 0, 0]]]}])
.then(function(gd) {
expect(gd._fullLayout.yaxis.range[0]).toBeGreaterThan(gd._fullLayout.yaxis.range[1]);
})
.catch(failTest)
.then(done);
});

it('should NOT reverse yaxis if another trace is present', function(done) {
Plotly.newPlot(gd, [{type: 'image', z: [[[255, 0, 0]]]}, {type: 'scatter', y: [5, 3, 2]}])
.then(function(gd) {
expect(gd._fullLayout.yaxis.range[1]).toBeGreaterThan(gd._fullLayout.yaxis.range[0]);
})
.catch(failTest)
.then(done);
});

it('should set scaleanchor to make square pixels if only images are present', function(done) {
Plotly.newPlot(gd, [{type: 'image', z: [[[255, 0, 0]]]}])
.then(function(gd) {
expect(gd._fullLayout.yaxis.scaleanchor).toBe('x');
})
.catch(failTest)
.then(done);
});

it('should NOT set scaleanchor if another trace is present', function(done) {
Plotly.newPlot(gd, [{type: 'image', z: [[[255, 0, 0]]]}, {type: 'scatter', y: [5, 3, 2]}])
.then(function(gd) {
expect(gd._fullLayout.yaxis.scaleanchor).toBe(undefined);
})
.catch(failTest)
.then(done);
});

it('should NOT set scaleanchor if it\'s already defined', function(done) {
Plotly.newPlot(gd, [
{type: 'image', z: [[[255, 0, 0]]]}, {type: 'scatter', y: [5, 3, 2]}
], {yaxis: {scaleanchor: 'x3'}})
.then(function(gd) {
expect(gd._fullLayout.yaxis.scaleanchor).toBe(undefined);
})
.catch(failTest)
.then(done);
});
});

describe('image plot', function() {
'use strict';

Expand Down Expand Up @@ -444,7 +500,7 @@ describe('image hover:', function() {
zmax: [1, 1, 1],
text: [['A', 'B', 'C'], ['D', 'E', 'F']],
hovertemplate: '%{text}<extra></extra>'
}], layout: {width: 400, height: 400}};
}], layout: {width: 400, height: 400, yaxis: {scaleanchor: null}}};

Plotly.newPlot(gd, mockCopy)
.then(function() {_hover(140, 200);})
Expand Down

0 comments on commit 5c42db8

Please sign in to comment.