Skip to content

Adding automargin support to plot titles #6428

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 63 commits into from
Mar 15, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
68c6165
Initial pass with hard-coded automargin params
hannahker Jan 6, 2023
ad6eb00
Remove role from schema
hannahker Jan 7, 2023
0826ddd
Merge branch 'master' into automargin-title
hannahker Jan 18, 2023
45d9cbf
Move automargin call
hannahker Jan 26, 2023
c6e31be
lint
archmoj Jan 27, 2023
f46014f
rename mock and generate baseline
archmoj Jan 27, 2023
587dfcb
update pie_automargin-margin0 baseline
archmoj Jan 27, 2023
3dae109
adjust pie test
archmoj Jan 27, 2023
61487a8
Simplify automargin title to use existing functions
hannahker Jan 30, 2023
8679e7d
Account for padding around title
hannahker Feb 6, 2023
e8e49a5
Adjust mock to yref=paper
hannahker Feb 7, 2023
2b59e2c
Temp fix for yref=paper
hannahker Feb 7, 2023
5e4ab42
Merge branch 'master' into automargin-title
hannahker Feb 16, 2023
4bb109e
Improve handling for paper ref and setting defaults
hannahker Feb 16, 2023
7ce1234
Fix formatting
hannahker Feb 16, 2023
b274642
Add jasmine test
hannahker Feb 16, 2023
cc15ff6
Simplify mock
hannahker Feb 17, 2023
938d52d
Fix test formatting
hannahker Feb 17, 2023
75636e2
Add simple implementation for container behaviour
hannahker Feb 18, 2023
b7e3295
Apply review comments
hannahker Feb 28, 2023
04f8825
Add more tests for yref=container
hannahker Feb 28, 2023
ad202d9
Ajust default setting
hannahker Feb 28, 2023
9611672
Remove outdated mock
hannahker Mar 1, 2023
c4d1076
Update mock baselines
hannahker Mar 1, 2023
21a9e59
Fix syntax
hannahker Mar 1, 2023
78cecff
Remove f from test
hannahker Mar 1, 2023
fd111d5
Set yanchor properly when title is at bottom
hannahker Mar 6, 2023
2a47c00
Make defaults setting logic more readable
hannahker Mar 7, 2023
52b37c0
Add reservedMargins logic
hannahker Mar 7, 2023
4322c7b
Revert some changes to test
hannahker Mar 7, 2023
73ccaf4
Fix bugs
hannahker Mar 8, 2023
a3462d2
Fix more bugs from redraw
hannahker Mar 8, 2023
33bbbef
Apply review comments
hannahker Mar 9, 2023
9af5cbd
Add jasmine test for interaction with x axis
hannahker Mar 9, 2023
67cf8da
Push pie test fix
hannahker Mar 9, 2023
16c0bcf
Fix scooting behaviour to account for reserved margin space
hannahker Mar 9, 2023
17c3244
Check if automargin is necessary before applying
hannahker Mar 10, 2023
c014702
Update tests
hannahker Mar 10, 2023
e59b18f
Warn when title.y is being set to 1
hannahker Mar 10, 2023
ddaf013
Fix syntax and another mock update
hannahker Mar 10, 2023
de7ca48
Apply review comments
hannahker Mar 10, 2023
e77126c
Calc bb for title
hannahker Mar 10, 2023
26ca553
Fix warning log
hannahker Mar 10, 2023
e5e8a2a
Update parameter description
hannahker Mar 10, 2023
d70fb46
Reposition properly
hannahker Mar 10, 2023
616057f
Merge branch 'master' into automargin-title
hannahker Mar 10, 2023
3523406
Only reposition title if necessary
hannahker Mar 10, 2023
90bd374
Fix syntax
hannahker Mar 10, 2023
158791f
Fix tests
hannahker Mar 10, 2023
c4e706e
Merge branch 'automargin-title-dev' into automargin-title
hannahker Mar 10, 2023
087c162
Adjust tests to match rendering in CI
hannahker Mar 13, 2023
c4d75d4
Update mocks
hannahker Mar 13, 2023
a257836
Add review comment
hannahker Mar 13, 2023
662628e
Update mock baselines
hannahker Mar 13, 2023
e4b5f29
Adjust titles on mocks
hannahker Mar 13, 2023
3dcaab8
Update baselines
hannahker Mar 13, 2023
2a0011a
Add milti-line title
hannahker Mar 14, 2023
a8185f4
Update baselines
hannahker Mar 14, 2023
0c0e47e
Revert dy change
hannahker Mar 14, 2023
7f89c73
move smart default for title.y and title.yanchor to supply defaults
archmoj Mar 10, 2023
132c57b
Adjust dy to fix offset
hannahker Mar 15, 2023
7d4e352
baseline update
archmoj Mar 15, 2023
ad7c6f0
Add draftlog
hannahker Mar 15, 2023
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
1 change: 1 addition & 0 deletions src/components/titles/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ function draw(gd, titleClass, options) {
else if(prop.indexOf('colorbar' !== -1)) editAttr = 'colorbarTitleText';
var editable = gd._context.edits[editAttr];


if(txt === '') opacity = 0;
// look for placeholder text while stripping out numbers from eg X2, Y3
// this is just for backward compatibility with the old version that had
Expand Down
1 change: 1 addition & 0 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ function _doPlot(gd, data, layout, config) {

subroutines.drawMarginPushers(gd);
Axes.allowAutoMargin(gd);
Plots.allowAutoMargin(gd, 'title.automargin');

// TODO can this be moved elsewhere?
if(fullLayout._has('pie')) {
Expand Down
89 changes: 79 additions & 10 deletions src/plot_api/subroutines.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var Registry = require('../registry');
var Plots = require('../plots/plots');

var Lib = require('../lib');
var svgTextUtils = require('../lib/svg_text_utils');
var clearGlCanvases = require('../lib/clear_gl_canvases');

var Color = require('../components/color');
Expand All @@ -22,6 +23,7 @@ var doAutoRange = require('../plots/cartesian/autorange').doAutoRange;
var SVG_TEXT_ANCHOR_START = 'start';
var SVG_TEXT_ANCHOR_MIDDLE = 'middle';
var SVG_TEXT_ANCHOR_END = 'end';
var LINE_SPACING = alignmentConstants.LINE_SPACING;

exports.layoutStyles = function(gd) {
return Lib.syncOrAsync([Plots.doAutoMargin, lsInner], gd);
Expand Down Expand Up @@ -397,24 +399,98 @@ function findCounterAxisLineWidth(ax, side, counterAx, axList) {
}

exports.drawMainTitle = function(gd) {
var title = gd._fullLayout.title;
setDflts(title);
var fullLayout = gd._fullLayout;

var textAnchor = getMainTitleTextAnchor(fullLayout);
var dy = getMainTitleDy(fullLayout);
var y = getMainTitleY(fullLayout, dy);
var position = fullLayout.title.y > 0.5 ? 't' : 'b';

if(gd._fullLayout.title.automargin) {
applyTitleAutoMargin(gd, position, y);
}

Titles.draw(gd, 'gtitle', {
propContainer: fullLayout,
propName: 'title.text',
placeholder: fullLayout._dfltTitle.plot,
attributes: {
x: getMainTitleX(fullLayout, textAnchor),
y: getMainTitleY(fullLayout, dy),
y: y,
'text-anchor': textAnchor,
dy: dy
}
});
};

// Is any part of the title outside of the container?
// TODO: What if yref='container'?
function isOutsideContainer(gd, title, position, y) {
var plotHeight = gd._fullLayout._size.h;
var yPosTop = Lib.isTopAnchor(title) ? y : y - titleDepth(title); // Standardize to the top of the title
var yPosRel = position === 'b' ? plotHeight - yPosTop : yPosTop; // Position relative to the top or bottom of plot
if((Lib.isTopAnchor(title) && position === 't') || Lib.isBottomAnchor(title) && position === 'b') {
return false;
} else {
if(yPosRel < titleDepth(title)) {
return true;
} else {
return false;
}
}
}

// TODO: Move to setting defaults stage, rather than drawing
// title.y is 1 or 0 if automargin and paper ref
function setDflts(title) {
if(title.automargin && title.yref === 'paper') {
title.y = title.y === 0 ? title.y : 1;
}
if(title.automargin) {
title.yanchor = title.yanchor === 'auto' ? 'bottom' : title.yanchor;
}
}

function titleDepth(title) {
var fontSize = title.font.size;
var extraLines = (title.text.match(svgTextUtils.BR_TAG_ALL) || []).length;
return extraLines ?
fontSize * (extraLines + 1) * LINE_SPACING :
fontSize;
}

function applyTitleAutoMargin(gd, position, y) {
var titleID = 'title.automargin';
var title = gd._fullLayout.title;
var push = {
x: title.x,
y: position === 't' ? 1 : 0, // TODO: Assuming that y is either 1 or 0?
t: 0,
b: 0
};

if(isOutsideContainer(gd, title, position, y)) {
push[position] = (
titleDepth(title) +
title.pad.t +
title.pad.b
);
}
Plots.allowAutoMargin(gd, titleID);
Plots.autoMargin(gd, titleID, push);
}

function getVPadShift(title, dy) {
var vPadShift = 0;
if(dy === '0em' || !dy) {
vPadShift = -title.pad.b;
} else if(dy === alignmentConstants.CAP_SHIFT + 'em') {
vPadShift = title.pad.t;
}
return vPadShift;
}

function getMainTitleX(fullLayout, textAnchor) {
var title = fullLayout.title;
var gs = fullLayout._size;
Expand All @@ -438,14 +514,7 @@ function getMainTitleX(fullLayout, textAnchor) {
function getMainTitleY(fullLayout, dy) {
var title = fullLayout.title;
var gs = fullLayout._size;
var vPadShift = 0;

if(dy === '0em' || !dy) {
vPadShift = -title.pad.b;
} else if(dy === alignmentConstants.CAP_SHIFT + 'em') {
vPadShift = title.pad.t;
}

var vPadShift = getVPadShift(title, dy);
if(title.y === 'auto') {
return gs.t / 2;
} else {
Expand Down
8 changes: 8 additions & 0 deletions src/plots/layout_attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,14 @@ module.exports = {
'Padding is muted if the respective anchor value is *middle*/*center*.'
].join(' ')
}),
automargin: {
valType: 'boolean',
dflt: false,
editType: 'plot',
description: [
'Determines whether the title can automatically push the figure margins.'
].join(' ')
},
editType: 'layoutstyle'
},
uniformtext: {
Expand Down
1 change: 1 addition & 0 deletions src/plots/plots.js
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,7 @@ plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut, formatObj) {
coerce('title.pad.r');
coerce('title.pad.b');
coerce('title.pad.l');
coerce('title.automargin');

var uniformtextMode = coerce('uniformtext.mode');
if(uniformtextMode) {
Expand Down
Binary file modified test/image/baselines/pie_automargin-margin0.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 added test/image/baselines/zzz-automargin-title.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions test/image/mocks/zzz-automargin-title.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"data": [
{
"showlegend": false,
"type": "scatter",
"x": [
1,
2,
3
],
"y": [
4,
5,
6
]
}],
"layout": {
"margin": {"t":0, "b": 0, "l": 0, "r": 0},
"title": {
"automargin": true,
"text": "Basic title",
"font": {"size": 24},
"pad": {"t": 15, "b": 10},
"yref": "paper"
}
}
}
2 changes: 1 addition & 1 deletion test/jasmine/tests/pie_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,7 @@ describe('Pie traces', function() {
textposition: [['outside', 'outside', 'inside', 'inside', 'outside']],
'outsidetextfont.size': 12
}, {
t: '~=', l: 'shrunk',
t: 'grew', l: 'shrunk',
b: 'grew', r: 'grew'
}))
.then(check('automargin:false', {automargin: false}, {
Expand Down
42 changes: 42 additions & 0 deletions test/jasmine/tests/titles_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1066,6 +1066,48 @@ describe('Titles for multiple axes', function() {
});
});

describe('Title automargining', function() {
'use strict';

var data = [{x: [1, 1, 3], y: [1, 2, 3]}];
var layout = {
'margin': {'t': 0, 'b': 0, 'l': 0, 'r': 0},
'title': {
'text': 'Basic title',
'font': {'size': 24},
'yref': 'paper'
}
};
var gd;

beforeEach(function() {
gd = createGraphDiv();
});

afterEach(destroyGraphDiv);

it('should avoid overlap with container for yref=paper and allow padding', function(done) {
Plotly.newPlot(gd, data, layout).then(function() {
expect(gd._fullLayout._size.t).toBe(0);
return Plotly.relayout(gd, 'title.automargin', true);
}).then(function() {
expect(gd._fullLayout.title.automargin).toBe(true);
expect(gd._fullLayout.title.y).toBe(1);
expect(gd._fullLayout.title.yanchor).toBe('bottom');
expect(gd._fullLayout._size.t).toBe(24);
return Plotly.relayout(gd, 'title.pad.t', 10);
}).then(function() {
expect(gd._fullLayout._size.t).toBe(34);
return Plotly.relayout(gd, 'title.pad.b', 10);
}).then(function() {
expect(gd._fullLayout._size.t).toBe(44);
return Plotly.relayout(gd, 'title.yanchor', 'top');
}).then(function() {
expect(gd._fullLayout._size.t).toBe(0);
}).then(done, done.fail);
});
});

function expectTitle(expTitle) {
expectTitleFn(expTitle)();
}
Expand Down
6 changes: 6 additions & 0 deletions test/plot-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -9425,6 +9425,12 @@
}
},
"title": {
"automargin": {
"description": "Determines whether the title can automatically push the figure margins.",
"dflt": false,
"editType": "plot",
"valType": "boolean"
},
"editType": "layoutstyle",
"font": {
"color": {
Expand Down