Skip to content

Commit e5a2f91

Browse files
committed
use editTypes for contour/contourcarpet-specific attributes
and validate `editTypes` in plotschema_test - one more step to cleaning the morass of attribute string literals out of restyle/relayout
1 parent 1bbdf59 commit e5a2f91

File tree

7 files changed

+225
-44
lines changed

7 files changed

+225
-44
lines changed

src/plot_api/edit_types.js

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* Copyright 2012-2017, Plotly, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
'use strict';
10+
11+
var isPlainObject = require('../lib/is_plain_object');
12+
13+
module.exports = {
14+
/*
15+
* default (all false) edit flags for restyle (traces)
16+
* creates a new object each call, so the caller can mutate freely
17+
*/
18+
traces: function() {
19+
return {
20+
docalc: false,
21+
docalcAutorange: false,
22+
doplot: false,
23+
dostyle: false,
24+
docolorbars: false,
25+
autorangeOn: false,
26+
clearCalc: false,
27+
fullReplot: false
28+
};
29+
},
30+
31+
/*
32+
* default (all false) edit flags for relayout
33+
* creates a new object each call, so the caller can mutate freely
34+
*/
35+
layout: function() {
36+
return {
37+
dolegend: false,
38+
doticks: false,
39+
dolayoutstyle: false,
40+
doplot: false,
41+
docalc: false,
42+
domodebar: false,
43+
docamera: false,
44+
layoutReplot: false
45+
};
46+
},
47+
48+
/*
49+
* update `flags` with the `editType` values found in `attr`
50+
*
51+
* If `attr` itself contains an `editType`, we just use that.
52+
* If it doesn't, we recurse into any other objects contained
53+
* in `attr` and update with all `editType` values found in
54+
* *any* of them.
55+
*
56+
* So container objects may not need their own `editType`,
57+
* if they're content to delegate to their members, but they
58+
* may provide one either for performance or, in case of arrays,
59+
* if adding/removing entries requires different flags than
60+
* simply changing attributes of an existing entry.
61+
*/
62+
update: function(flags, attr) {
63+
function extend(attr1) {
64+
var editType = attr1.editType;
65+
if(editType === undefined) {
66+
// if there's no editType defined, recurse into
67+
Object.keys(attr1).forEach(function(attrName) {
68+
var attr2 = attr1[attrName];
69+
if(attrName.charAt(0) !== '_' && isPlainObject(attr2)) {
70+
extend(attr2);
71+
}
72+
});
73+
}
74+
else {
75+
var editTypeParts = editType.split('+');
76+
editTypeParts.forEach(function(part) {
77+
flags[part] = true;
78+
});
79+
}
80+
}
81+
82+
extend(attr);
83+
}
84+
};

src/plot_api/plot_api.js

+30-39
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ var svgTextUtils = require('../lib/svg_text_utils');
3131
var manageArrays = require('./manage_arrays');
3232
var helpers = require('./helpers');
3333
var subroutines = require('./subroutines');
34+
var editTypes = require('./edit_types');
35+
3436
var cartesianConstants = require('../plots/cartesian/constants');
3537
var axisConstraints = require('../plots/cartesian/constraints');
3638
var enforceAxisConstraints = axisConstraints.enforce;
@@ -1264,16 +1266,7 @@ function _restyle(gd, aobj, _traces) {
12641266
var traces = helpers.coerceTraceIndices(gd, _traces);
12651267

12661268
// initialize flags
1267-
var flags = {
1268-
docalc: false,
1269-
docalcAutorange: false,
1270-
doplot: false,
1271-
dostyle: false,
1272-
docolorbars: false,
1273-
autorangeOn: false,
1274-
clearCalc: false,
1275-
fullReplot: false
1276-
};
1269+
var flags = editTypes.traces();
12771270

12781271
// copies of the change (and previous values of anything affected)
12791272
// for the undo / redo queue
@@ -1304,8 +1297,6 @@ function _restyle(gd, aobj, _traces) {
13041297
'reversescale', 'marker.reversescale',
13051298
'autobinx', 'nbinsx', 'xbins', 'xbins.start', 'xbins.end', 'xbins.size',
13061299
'autobiny', 'nbinsy', 'ybins', 'ybins.start', 'ybins.end', 'ybins.size',
1307-
'autocontour', 'ncontours', 'contours', 'contours.coloring',
1308-
'contours.operation', 'contours.value', 'contours.type', 'contours.value[0]', 'contours.value[1]',
13091300
'error_y', 'error_y.visible', 'error_y.value', 'error_y.type',
13101301
'error_y.traceref', 'error_y.array', 'error_y.symmetric',
13111302
'error_y.arrayminus', 'error_y.valueminus', 'error_y.tracerefminus',
@@ -1373,9 +1364,6 @@ function _restyle(gd, aobj, _traces) {
13731364
'marker.cmin', 'marker.cmax', 'marker.cauto',
13741365
'line.cmin', 'line.cmax',
13751366
'marker.line.cmin', 'marker.line.cmax',
1376-
'contours.start', 'contours.end', 'contours.size',
1377-
'contours.showlines', 'contours.showlabels', 'contours.labelformat',
1378-
'contours.font', 'contours.font.family', 'contours.font.size',
13791367
'line', 'line.smoothing', 'line.shape',
13801368
'error_y.width', 'error_x.width', 'error_x.copy_ystyle',
13811369
'marker.maxdisplayed'
@@ -1620,23 +1608,35 @@ function _restyle(gd, aobj, _traces) {
16201608
flags.docalc = true;
16211609
}
16221610
else {
1623-
var moduleAttrs = (contFull._module || {}).attributes || {};
1624-
var valObject = Lib.nestedProperty(moduleAttrs, ai).get() ||
1625-
Lib.nestedProperty(Plots.attributes, ai).get() ||
1626-
{};
1611+
var aiHead = param.parts[0];
1612+
var moduleAttrs = (contFull._module || {}).attributes;
1613+
var valObject = moduleAttrs && moduleAttrs[aiHead];
1614+
if(!valObject) valObject = Plots.attributes[aiHead];
1615+
if(valObject) {
1616+
/*
1617+
* In occasional cases we can't the innermost valObject
1618+
* doesn't exist, for example `valType: 'any'` items like
1619+
* contourcarpet `contours.value` where we might set
1620+
* `contours.value[0]`. In that case, stop at the deepest
1621+
* valObject we *do* find.
1622+
*/
1623+
for(var parti = 1; parti < param.parts.length; parti++) {
1624+
var newValObject = valObject[param.parts[parti]];
1625+
if(newValObject) valObject = newValObject;
1626+
else break;
1627+
}
16271628

1628-
// if restyling entire attribute container, assume worse case
1629-
if(!valObject.valType) {
1630-
flags.docalc = true;
1631-
}
1629+
// must redo calcdata when restyling array values of arrayOk attributes
1630+
if(valObject.arrayOk && (Array.isArray(newVal) || Array.isArray(oldVal))) {
1631+
flags.docalc = true;
1632+
}
16321633

1633-
// must redo calcdata when restyling array values of arrayOk attributes
1634-
if(valObject.arrayOk && (Array.isArray(newVal) || Array.isArray(oldVal))) {
1635-
flags.docalc = true;
1634+
// some attributes declare an 'editType' flaglist
1635+
editTypes.update(flags, valObject);
16361636
}
1637-
1638-
// some attributes declare an 'editType' flaglist
1639-
if(valObject.editType === 'docalc') {
1637+
else {
1638+
// if we couldn't find valObject even at the root,
1639+
// assume a full recalc.
16401640
flags.docalc = true;
16411641
}
16421642

@@ -1864,16 +1864,7 @@ function _relayout(gd, aobj) {
18641864
}
18651865

18661866
// initialize flags
1867-
var flags = {
1868-
dolegend: false,
1869-
doticks: false,
1870-
dolayoutstyle: false,
1871-
doplot: false,
1872-
docalc: false,
1873-
domodebar: false,
1874-
docamera: false,
1875-
layoutReplot: false
1876-
};
1867+
var flags = editTypes.layout();
18771868

18781869
// copies of the change (and previous values of anything affected)
18791870
// for the undo / redo queue

src/plot_api/plot_schema.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ var animationAttributes = require('../plots/animation_attributes');
2121
var polarAreaAttrs = require('../plots/polar/area_attributes');
2222
var polarAxisAttrs = require('../plots/polar/axis_attributes');
2323

24+
var editTypes = require('./edit_types');
25+
2426
var extendFlat = Lib.extendFlat;
2527
var extendDeep = Lib.extendDeep;
2628

@@ -62,7 +64,11 @@ exports.get = function() {
6264
return {
6365
defs: {
6466
valObjects: Lib.valObjects,
65-
metaKeys: UNDERSCORE_ATTRS.concat(['description', 'role'])
67+
metaKeys: UNDERSCORE_ATTRS.concat(['description', 'role']),
68+
editTypes: {
69+
traces: editTypes.traces(),
70+
layout: editTypes.layout()
71+
}
6672
},
6773

6874
traces: traces,

src/traces/contour/attributes.js

+14-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ module.exports = extendFlat({}, {
3737
valType: 'boolean',
3838
dflt: true,
3939
role: 'style',
40+
editType: 'docalc',
4041
description: [
4142
'Determines whether or not the contour level attributes are',
4243
'picked by an algorithm.',
@@ -49,6 +50,7 @@ module.exports = extendFlat({}, {
4950
dflt: 15,
5051
min: 1,
5152
role: 'style',
53+
editType: 'docalc',
5254
description: [
5355
'Sets the maximum number of contour levels. The actual number',
5456
'of contours will be chosen automatically to be less than or',
@@ -63,6 +65,7 @@ module.exports = extendFlat({}, {
6365
valType: 'number',
6466
dflt: null,
6567
role: 'style',
68+
editType: 'doplot',
6669
description: [
6770
'Sets the starting contour level value.',
6871
'Must be less than `contours.end`'
@@ -72,6 +75,7 @@ module.exports = extendFlat({}, {
7275
valType: 'number',
7376
dflt: null,
7477
role: 'style',
78+
editType: 'doplot',
7579
description: [
7680
'Sets the end contour level value.',
7781
'Must be more than `contours.start`'
@@ -82,6 +86,7 @@ module.exports = extendFlat({}, {
8286
dflt: null,
8387
min: 0,
8488
role: 'style',
89+
editType: 'doplot',
8590
description: [
8691
'Sets the step between each contour level.',
8792
'Must be positive.'
@@ -92,6 +97,7 @@ module.exports = extendFlat({}, {
9297
values: ['fill', 'heatmap', 'lines', 'none'],
9398
dflt: 'fill',
9499
role: 'style',
100+
editType: 'docalc',
95101
description: [
96102
'Determines the coloring method showing the contour values.',
97103
'If *fill*, coloring is done evenly between each contour level',
@@ -105,6 +111,7 @@ module.exports = extendFlat({}, {
105111
valType: 'boolean',
106112
dflt: true,
107113
role: 'style',
114+
editType: 'doplot',
108115
description: [
109116
'Determines whether or not the contour lines are drawn.',
110117
'Has an effect only if `contours.coloring` is set to *fill*.'
@@ -114,6 +121,7 @@ module.exports = extendFlat({}, {
114121
valType: 'boolean',
115122
dflt: false,
116123
role: 'style',
124+
editType: 'doplot',
117125
description: [
118126
'Determines whether to label the contour lines with their values.'
119127
].join(' ')
@@ -123,12 +131,16 @@ module.exports = extendFlat({}, {
123131
'Sets the font used for labeling the contour levels.',
124132
'The default color comes from the lines, if shown.',
125133
'The default family and size come from `layout.font`.'
126-
].join(' ')
134+
].join(' '),
135+
family: extendFlat({}, fontAttrs.family, {editType: 'doplot'}),
136+
size: extendFlat({}, fontAttrs.size, {editType: 'doplot'}),
137+
color: extendFlat({}, fontAttrs.color, {editType: 'dostyle'})
127138
}),
128139
labelformat: {
129140
valType: 'string',
130141
dflt: '',
131142
role: 'style',
143+
editType: 'doplot',
132144
description: [
133145
'Sets the contour label formatting rule using d3 formatting',
134146
'mini-language which is very similar to Python, see:',
@@ -141,7 +153,7 @@ module.exports = extendFlat({}, {
141153
color: extendFlat({}, scatterLineAttrs.color, {
142154
description: [
143155
'Sets the color of the contour level.',
144-
'Has no if `contours.coloring` is set to *lines*.'
156+
'Has no effect if `contours.coloring` is set to *lines*.'
145157
].join(' ')
146158
}),
147159
width: scatterLineAttrs.width,

src/traces/contourcarpet/attributes.js

+4
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ module.exports = extendFlat({}, {
6969
values: ['levels', 'constraint'],
7070
dflt: 'levels',
7171
role: 'info',
72+
editType: 'docalc',
7273
description: [
7374
'If `levels`, the data is represented as a contour plot with multiple',
7475
'levels displayed. If `constraint`, the data is represented as constraints',
@@ -85,6 +86,7 @@ module.exports = extendFlat({}, {
8586
values: ['fill', 'lines', 'none'],
8687
dflt: 'fill',
8788
role: 'style',
89+
editType: 'docalc',
8890
description: [
8991
'Determines the coloring method showing the contour values.',
9092
'If *fill*, coloring is done evenly between each contour level',
@@ -101,6 +103,7 @@ module.exports = extendFlat({}, {
101103
values: [].concat(constants.INEQUALITY_OPS).concat(constants.INTERVAL_OPS).concat(constants.SET_OPS),
102104
role: 'info',
103105
dflt: '=',
106+
editType: 'docalc',
104107
description: [
105108
'Sets the filter operation.',
106109

@@ -127,6 +130,7 @@ module.exports = extendFlat({}, {
127130
valType: 'any',
128131
dflt: 0,
129132
role: 'info',
133+
editType: 'docalc',
130134
description: [
131135
'Sets the value or values by which to filter by.',
132136

0 commit comments

Comments
 (0)