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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

add options to include shapes and newshape in legends #6653

Merged
merged 30 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
6545353
register legends after shapes
archmoj Jun 27, 2023
786d9e6
add options to include shapes in legends
archmoj Jun 27, 2023
2d7d3da
test clicking shape legends
archmoj Jun 28, 2023
332a0dd
draftlog
archmoj Jun 28, 2023
8a0f60a
improve descriptions
archmoj Jun 28, 2023
f0c6b72
add comments to core.js about order of registering components
archmoj Jun 29, 2023
d3004c1
use hexagon2 for path symbols
archmoj Jun 29, 2023
51a28f9
use overrideAll in newshape and fix bundling issue
archmoj Jun 29, 2023
0fa6914
Merge branch 'master' into shape-legends
archmoj Jun 30, 2023
4728e86
Merge remote-tracking branch 'origin/master' into shape-legends
archmoj Jul 4, 2023
2f1f812
Merge remote-tracking branch 'origin/master' into shape-legends
archmoj Jul 5, 2023
3511eb4
test showing shapes in groups
archmoj Jul 5, 2023
8e181cc
rename vars to point to data updates
archmoj Jul 6, 2023
6c0ab2e
handle shape legends group click
archmoj Jul 6, 2023
7870720
avoid unrecognized messages on click
archmoj Jul 7, 2023
ef0fe6f
add grouptitle and handle click
archmoj Jul 7, 2023
2e77fc7
test legendrank
archmoj Jul 7, 2023
58b1cb1
mention traces and shapes order in legendrank description
archmoj Jul 7, 2023
3168078
test shape legends and groups in multiple legends
archmoj Jul 7, 2023
6343338
add name to newshape and improve descriptions
archmoj Jul 17, 2023
7bf5029
coerce newshape.name
archmoj Jul 17, 2023
948fd02
add name to newshapes when creating a new one
archmoj Jul 18, 2023
e5a600d
Update src/components/shapes/draw_newshape/attributes.js
archmoj Jul 18, 2023
5b02b62
more name appears fixes and update the schema
archmoj Jul 18, 2023
b35add8
fix shape.name updates via editing legends
archmoj Jul 18, 2023
6111aba
fix double click shape legends
archmoj Jul 19, 2023
5c0168c
simplify handling shape legends in click
archmoj Jul 20, 2023
15986b8
jasmine tests for editable shape legends
archmoj Jul 21, 2023
759dbb4
use update instead of restyle & relayout when updating shape legends
archmoj Jul 24, 2023
9123425
Merge remote-tracking branch 'origin/master' into shape-legends
archmoj Jul 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/components/colorbar/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ function makeColorBarData(gd) {
for(var i = 0; i < calcdata.length; i++) {
var cd = calcdata[i];
trace = cd[0].trace;
if(!trace._module) continue;
var moduleOpts = trace._module.colorbar;

if(trace.visible === true && moduleOpts) {
Expand Down
28 changes: 24 additions & 4 deletions src/components/legend/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,17 +195,37 @@ function groupDefaults(legendId, layoutIn, layoutOut, fullData) {

module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
var i;
var legends = ['legend'];

for(i = 0; i < fullData.length; i++) {
Lib.pushUnique(legends, fullData[i].legend);
var allLegendsData = fullData.slice();

// shapes could also show up in legends
var shapes = layoutOut.shapes;
if(shapes) {
for(i = 0; i < shapes.length; i++) {
var shape = shapes[i];
if(!shape.showlegend) continue;

var mockTrace = {
_input: shape._input,
visible: shape.visible,
showlegend: shape.showlegend,
legend: shape.legend
};

allLegendsData.push(mockTrace);
}
}

var legends = ['legend'];
for(i = 0; i < allLegendsData.length; i++) {
Lib.pushUnique(legends, allLegendsData[i].legend);
}

layoutOut._legends = [];
for(i = 0; i < legends.length; i++) {
var legendId = legends[i];

groupDefaults(legendId, layoutIn, layoutOut, fullData);
groupDefaults(legendId, layoutIn, layoutOut, allLegendsData);

if(
layoutOut[legendId] &&
Expand Down
35 changes: 33 additions & 2 deletions src/components/legend/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,39 @@ function drawOne(gd, opts) {

var legendData;
if(!inHover) {
if(!gd.calcdata) return;
legendData = fullLayout.showlegend && getLegendData(gd.calcdata, legendObj, fullLayout._legends.length > 1);
var calcdata = (gd.calcdata || []).slice();

var shapes = fullLayout.shapes;
for(var i = 0; i < shapes.length; i++) {
var shape = shapes[i];
if(!shape.showlegend) continue;

var shapeLegend = {
_fullInput: shape,
index: shape._index,
name: shape.name || shape.label.text || ('shape ' + shape._index),
LiamConnors marked this conversation as resolved.
Show resolved Hide resolved
legend: shape.legend,
legendgroup: shape.legendgroup,
legendgrouptitle: shape.legendgrouptitle,
legendrank: shape.legendrank,
legendwidth: shape.legendwidth,
showlegend: shape.showlegend,
visible: shape.visible,
opacity: shape.opacity,
mode: shape.type === 'line' ? 'lines' : 'markers',
line: shape.line,
marker: {
line: shape.line,
color: shape.fillcolor,
symbol: shape.type === 'rect' ? 'square' : 'circle',
alexcjohnson marked this conversation as resolved.
Show resolved Hide resolved
size: 12
},
};

calcdata.push([{ trace: shapeLegend }]);
}
if(!calcdata.length) return;
legendData = fullLayout.showlegend && getLegendData(calcdata, legendObj, fullLayout._legends.length > 1);
} else {
if(!legendObj.entries) return;
legendData = getLegendData(legendObj.entries, legendObj);
Expand Down
16 changes: 12 additions & 4 deletions src/components/legend/handle_click.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,17 @@ module.exports = function handleClick(g, gd, numClicks) {
if(legendItem.groupTitle && !toggleGroup) return;

var fullInput = fullTrace._fullInput;
var isShape = fullInput._isShape;
if(isShape) fullInput = fullTrace;
var index = fullInput.index;

if(Registry.hasTransform(fullInput, 'groupby')) {
var kcont = carrs[fullInput.index];
var kcont = carrs[index];
if(!kcont) {
var groupbyIndices = Registry.getTransformIndices(fullInput, 'groupby');
var lastGroupbyIndex = groupbyIndices[groupbyIndices.length - 1];
kcont = Lib.keyedContainer(fullInput, 'transforms[' + lastGroupbyIndex + '].styles', 'target', 'value.visible');
carrs[fullInput.index] = kcont;
carrs[index] = kcont;
}

var curState = kcont.get(fullTrace._group);
Expand All @@ -92,14 +96,18 @@ module.exports = function handleClick(g, gd, numClicks) {
// true -> legendonly. All others toggle to true:
kcont.set(fullTrace._group, visibility);
}
carrIdx[fullInput.index] = insertUpdate(fullInput.index, 'visible', fullInput.visible === false ? false : true);
carrIdx[index] = insertUpdate(index, 'visible', fullInput.visible === false ? false : true);
} else {
// false -> false (not possible since will not be visible in legend)
// true -> legendonly
// legendonly -> true
var nextVisibility = fullInput.visible === false ? false : visibility;

insertUpdate(fullInput.index, 'visible', nextVisibility);
if(isShape) {
Registry.call('_guiRelayout', gd, 'shapes[' + index + '].visible', nextVisibility);
} else {
insertUpdate(index, 'visible', nextVisibility);
}
}
}

Expand Down
41 changes: 38 additions & 3 deletions src/components/shapes/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,54 @@ var dash = require('../drawing/attributes').dash;
var extendFlat = require('../../lib/extend').extendFlat;
var templatedArray = require('../../plot_api/plot_template').templatedArray;
var axisPlaceableObjs = require('../../constants/axis_placeable_objects');
var basePlotAttributes = require('../../plots/attributes');
var shapeTexttemplateAttrs = require('../../plots/template_attributes').shapeTexttemplateAttrs;
var shapeLabelTexttemplateVars = require('./label_texttemplate');

module.exports = templatedArray('shape', {
visible: {
visible: extendFlat({}, basePlotAttributes.visible, {
editType: 'calc+arraydraw'
alexcjohnson marked this conversation as resolved.
Show resolved Hide resolved
}),

showlegend: {
valType: 'boolean',
dflt: true,
dflt: false,
editType: 'calc+arraydraw',
description: [
'Determines whether or not this shape is visible.'
'Determines whether or not this',
'shape is shown in the legend.'
].join(' ')
},

legend: extendFlat({}, basePlotAttributes.legend, {
editType: 'calc+arraydraw'
}),

legendgroup: extendFlat({}, basePlotAttributes.legendgroup, {
editType: 'calc+arraydraw'
}),

legendgrouptitle: {
text: extendFlat({}, basePlotAttributes.legendgrouptitle.text, {
editType: 'calc+arraydraw'
}),
font: fontAttrs({
editType: 'calc+arraydraw',
description: [
'Sets this legend group\'s title font.'
].join(' '),
}),
editType: 'calc+arraydraw',
},

legendrank: extendFlat({}, basePlotAttributes.legendrank, {
editType: 'calc+arraydraw'
}),

legendwidth: extendFlat({}, basePlotAttributes.legendwidth, {
editType: 'calc+arraydraw'
}),

type: {
valType: 'enumerated',
values: ['circle', 'rect', 'path', 'line'],
Expand Down
12 changes: 12 additions & 0 deletions src/components/shapes/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,21 @@ function handleShapeDefaults(shapeIn, shapeOut, fullLayout) {
return Lib.coerce(shapeIn, shapeOut, attributes, attr, dflt);
}

shapeOut._isShape = true;

var visible = coerce('visible');
if(!visible) return;

var showlegend = coerce('showlegend');
if(showlegend) {
coerce('legend');
coerce('legendwidth');
coerce('legendgroup');
coerce('legendgrouptitle.text');
Lib.coerceFont(coerce, 'legendgrouptitle.font');
coerce('legendrank');
}

var path = coerce('path');
var dfltType = path ? 'path' : 'rect';
var shapeType = coerce('type', dfltType);
Expand Down
4 changes: 2 additions & 2 deletions src/components/shapes/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function draw(gd) {
}

for(var i = 0; i < fullLayout.shapes.length; i++) {
if(fullLayout.shapes[i].visible) {
if(fullLayout.shapes[i].visible === true) {
drawOne(gd, i);
}
}
Expand Down Expand Up @@ -89,7 +89,7 @@ function drawOne(gd, index) {

// this shape is gone - quit now after deleting it
// TODO: use d3 idioms instead of deleting and redrawing every time
if(!options._input || options.visible === false) return;
if(!options._input || options.visible !== true) return;

if(options.layer !== 'below') {
drawShape(gd._fullLayout._shapeUpperLayer);
Expand Down
44 changes: 44 additions & 0 deletions src/components/shapes/draw_newshape/attributes.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';

var basePlotAttributes = require('../../../plots/attributes');
var fontAttrs = require('../../../plots/font_attributes');
var dash = require('../../drawing/attributes').dash;
var extendFlat = require('../../../lib/extend').extendFlat;
Expand All @@ -9,6 +10,49 @@ var shapeLabelTexttemplateVars = require('../label_texttemplate');

module.exports = {
newshape: {
visible: extendFlat({}, basePlotAttributes.visible, {
editType: 'none'
}),

showlegend: {
valType: 'boolean',
dflt: false,
editType: 'none',
description: [
'Determines whether or not new',
'shape is shown in the legend.'
].join(' ')
},

legend: extendFlat({}, basePlotAttributes.legend, {
editType: 'none'
}),

legendgroup: extendFlat({}, basePlotAttributes.legendgroup, {
editType: 'none'
}),

legendgrouptitle: {
text: extendFlat({}, basePlotAttributes.legendgrouptitle.text, {
editType: 'none'
}),
font: fontAttrs({
editType: 'none',
description: [
'Sets this legend group\'s title font.'
].join(' '),
}),
editType: 'none',
},

legendrank: extendFlat({}, basePlotAttributes.legendrank, {
editType: 'none'
}),

legendwidth: extendFlat({}, basePlotAttributes.legendwidth, {
editType: 'none'
}),

line: {
color: {
valType: 'color',
Expand Down
10 changes: 10 additions & 0 deletions src/components/shapes/draw_newshape/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ function dfltLabelYanchor(isLine, labelTextPosition) {
}

module.exports = function supplyDrawNewShapeDefaults(layoutIn, layoutOut, coerce) {
coerce('newshape.visible');

coerce('newshape.showlegend');
coerce('newshape.legend');
coerce('newshape.legendwidth');
coerce('newshape.legendgroup');
coerce('newshape.legendgrouptitle.text');
Lib.coerceFont(coerce, 'newshape.legendgrouptitle.font');
coerce('newshape.legendrank');

coerce('newshape.drawdirection');
coerce('newshape.layer');
coerce('newshape.fillcolor');
Expand Down
12 changes: 12 additions & 0 deletions src/components/shapes/draw_newshape/newshapes.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,18 @@ function createShapeObj(outlines, dragOptions, dragmode) {
var newShape = {
editable: true,

visible: newStyle.visible,

showlegend: newStyle.showlegend,
legend: newStyle.legend,
legendwidth: newStyle.legendwidth,
legendgroup: newStyle.legendgroup,
legendgrouptitle: {
text: newStyle.legendgrouptitle.text,
font: newStyle.legendgrouptitle.font
},
legendrank: newStyle.legendrank,

label: newStyle.label,

xref: xPaper ? 'paper' : xaxis._id,
Expand Down
4 changes: 2 additions & 2 deletions src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ register(require('./traces/scatter'));

// register all registrable components modules
register([
require('./components/legend'),
require('./components/fx'), // fx needs to come after legend
require('./components/annotations'),
require('./components/annotations3d'),
require('./components/selections'),
Expand All @@ -46,6 +44,8 @@ register([
require('./components/errorbars'),
require('./components/colorscale'),
require('./components/colorbar'),
require('./components/legend'),
require('./components/fx'), // fx needs to come after legend
alexcjohnson marked this conversation as resolved.
Show resolved Hide resolved
require('./components/modebar')
]);

Expand Down
9 changes: 9 additions & 0 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -2228,6 +2228,15 @@ function _relayout(gd, aobj) {
// couldn't editType do this?
if(updateAutosize(gd) || aobj.height || aobj.width) flags.plot = true;

// update shape legends
var shapes = fullLayout.shapes;
for(i = 0; i < shapes.length; i++) {
if(shapes[i].showlegend) {
flags.calc = true;
break;
}
}

if(flags.plot || flags.calc) {
flags.layoutReplot = true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/plots/get_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ exports.getModuleCalcData = function(calcdata, arg1) {
// would suggest), but by 'module plot method' so that if some traces
// share the same module plot method (e.g. bar and histogram), we
// only call it one!
if(trace._module.plot === plotMethod) {
if(trace._module && trace._module.plot === plotMethod) {
moduleCalcData.push(cd);
} else {
remainingCalcData.push(cd);
Expand Down
Binary file modified test/image/baselines/text_on_shapes_basic.png
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/text_on_shapes_reversed_axes.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 21 additions & 2 deletions test/image/mocks/multi-legends.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,28 @@
"text": "Legend 3"
}
},
"hovermode": "x unified"
"hovermode": "x unified",
"dragmode": "drawline",
"newshape": {
"legend": "legend2",
"line": {
"color": "pink"
},
"label": {
"text": "new shape"
},
"showlegend": true
}
},
"config": {
"editable": true
"editable": true,
"modeBarButtonsToAdd": [
"drawline",
"drawopenpath",
"drawclosedpath",
"drawcircle",
"drawrect",
"eraseshape"
]
}
}