Skip to content

Commit e26bc50

Browse files
committed
Retain bar text styles throughout selection as well [2951]
- Note: even before the introduction of defaulting to contrasting colors for inside text labels, font inheritance wasn't working throughout selection.
1 parent d2dbd28 commit e26bc50

File tree

4 files changed

+274
-115
lines changed

4 files changed

+274
-115
lines changed

src/traces/bar/helpers.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* Copyright 2012-2018, 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 isNumeric = require('fast-isnumeric');
12+
var tinycolor = require('tinycolor2');
13+
14+
exports.coerceString = function(attributeDefinition, value, defaultValue) {
15+
if(typeof value === 'string') {
16+
if(value || !attributeDefinition.noBlank) return value;
17+
}
18+
else if(typeof value === 'number') {
19+
if(!attributeDefinition.strict) return String(value);
20+
}
21+
22+
return (defaultValue !== undefined) ?
23+
defaultValue :
24+
attributeDefinition.dflt;
25+
};
26+
27+
exports.coerceNumber = function(attributeDefinition, value, defaultValue) {
28+
if(isNumeric(value)) {
29+
value = +value;
30+
31+
var min = attributeDefinition.min,
32+
max = attributeDefinition.max,
33+
isOutOfBounds = (min !== undefined && value < min) ||
34+
(max !== undefined && value > max);
35+
36+
if(!isOutOfBounds) return value;
37+
}
38+
39+
return (defaultValue !== undefined) ?
40+
defaultValue :
41+
attributeDefinition.dflt;
42+
};
43+
44+
exports.coerceColor = function(attributeDefinition, value, defaultValue) {
45+
if(tinycolor(value).isValid()) return value;
46+
47+
return (defaultValue !== undefined) ?
48+
defaultValue :
49+
attributeDefinition.dflt;
50+
};
51+
52+
exports.coerceEnumerated = function(attributeDefinition, value, defaultValue) {
53+
if(attributeDefinition.coerceNumber) value = +value;
54+
55+
if(attributeDefinition.values.indexOf(value) !== -1) return value;
56+
57+
return (defaultValue !== undefined) ?
58+
defaultValue :
59+
attributeDefinition.dflt;
60+
};
61+
62+
exports.getValue = function(arrayOrScalar, index) {
63+
var value;
64+
if(!Array.isArray(arrayOrScalar)) value = arrayOrScalar;
65+
else if(index < arrayOrScalar.length) value = arrayOrScalar[index];
66+
return value;
67+
};

src/traces/bar/plot.js

Lines changed: 11 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
var d3 = require('d3');
1313
var isNumeric = require('fast-isnumeric');
14-
var tinycolor = require('tinycolor2');
1514

1615
var Lib = require('../../lib');
1716
var svgTextUtils = require('../../lib/svg_text_utils');
@@ -22,10 +21,9 @@ var Registry = require('../../registry');
2221

2322
var attributes = require('./attributes'),
2423
attributeText = attributes.text,
25-
attributeTextPosition = attributes.textposition,
26-
attributeTextFont = attributes.textfont,
27-
attributeInsideTextFont = attributes.insidetextfont,
28-
attributeOutsideTextFont = attributes.outsidetextfont;
24+
attributeTextPosition = attributes.textposition;
25+
var helpers = require('./helpers');
26+
var style = require('./style');
2927

3028
// padding in pixels around text
3129
var TEXTPAD = 3;
@@ -177,9 +175,10 @@ function appendBarText(gd, bar, calcTrace, i, x0, x1, y0, y1) {
177175
return;
178176
}
179177

180-
var textFont = getTextFont(trace, i, gd._fullLayout.font),
181-
insideTextFont = getInsideTextFont(trace, i, textFont, calcTrace[i].mc),
182-
outsideTextFont = getOutsideTextFont(trace, i, textFont);
178+
var layoutFont = gd._fullLayout.font;
179+
var barColor = calcTrace[i].mc;
180+
var insideTextFont = style.getInsideTextFont(trace, i, layoutFont, barColor);
181+
var outsideTextFont = style.getOutsideTextFont(trace, i, layoutFont);
183182

184183
// compute text position
185184
var barmode = gd._fullLayout.barmode,
@@ -429,109 +428,11 @@ function getTransform(textX, textY, targetX, targetY, scale, rotate) {
429428
}
430429

431430
function getText(trace, index) {
432-
var value = getValue(trace.text, index);
433-
return coerceString(attributeText, value);
431+
var value = helpers.getValue(trace.text, index);
432+
return helpers.coerceString(attributeText, value);
434433
}
435434

436435
function getTextPosition(trace, index) {
437-
var value = getValue(trace.textposition, index);
438-
return coerceEnumerated(attributeTextPosition, value);
439-
}
440-
441-
function getTextFont(trace, index, defaultValue) {
442-
return getFontValue(
443-
attributeTextFont, trace.textfont, index, defaultValue);
444-
}
445-
446-
function getInsideTextFont(trace, index, defaultFont, barColor) {
447-
var wouldFallBackToLayoutFont =
448-
(trace._input.textfont === undefined || trace._input.textfont.color === undefined) ||
449-
(Array.isArray(trace.textfont.color) && trace.textfont.color[index] === undefined);
450-
if(wouldFallBackToLayoutFont) {
451-
defaultFont = {
452-
color: Color.contrast(barColor),
453-
family: defaultFont.family,
454-
size: defaultFont.size
455-
};
456-
}
457-
458-
return getFontValue(
459-
attributeInsideTextFont, trace.insidetextfont, index, defaultFont);
460-
}
461-
462-
function getOutsideTextFont(trace, index, defaultValue) {
463-
return getFontValue(
464-
attributeOutsideTextFont, trace.outsidetextfont, index, defaultValue);
465-
}
466-
467-
function getFontValue(attributeDefinition, attributeValue, index, defaultValue) {
468-
attributeValue = attributeValue || {};
469-
470-
var familyValue = getValue(attributeValue.family, index),
471-
sizeValue = getValue(attributeValue.size, index),
472-
colorValue = getValue(attributeValue.color, index);
473-
474-
return {
475-
family: coerceString(
476-
attributeDefinition.family, familyValue, defaultValue.family),
477-
size: coerceNumber(
478-
attributeDefinition.size, sizeValue, defaultValue.size),
479-
color: coerceColor(
480-
attributeDefinition.color, colorValue, defaultValue.color)
481-
};
482-
}
483-
484-
function getValue(arrayOrScalar, index) {
485-
var value;
486-
if(!Array.isArray(arrayOrScalar)) value = arrayOrScalar;
487-
else if(index < arrayOrScalar.length) value = arrayOrScalar[index];
488-
return value;
489-
}
490-
491-
function coerceString(attributeDefinition, value, defaultValue) {
492-
if(typeof value === 'string') {
493-
if(value || !attributeDefinition.noBlank) return value;
494-
}
495-
else if(typeof value === 'number') {
496-
if(!attributeDefinition.strict) return String(value);
497-
}
498-
499-
return (defaultValue !== undefined) ?
500-
defaultValue :
501-
attributeDefinition.dflt;
502-
}
503-
504-
function coerceEnumerated(attributeDefinition, value, defaultValue) {
505-
if(attributeDefinition.coerceNumber) value = +value;
506-
507-
if(attributeDefinition.values.indexOf(value) !== -1) return value;
508-
509-
return (defaultValue !== undefined) ?
510-
defaultValue :
511-
attributeDefinition.dflt;
512-
}
513-
514-
function coerceNumber(attributeDefinition, value, defaultValue) {
515-
if(isNumeric(value)) {
516-
value = +value;
517-
518-
var min = attributeDefinition.min,
519-
max = attributeDefinition.max,
520-
isOutOfBounds = (min !== undefined && value < min) ||
521-
(max !== undefined && value > max);
522-
523-
if(!isOutOfBounds) return value;
524-
}
525-
526-
return (defaultValue !== undefined) ?
527-
defaultValue :
528-
attributeDefinition.dflt;
529-
}
530-
531-
function coerceColor(attributeDefinition, value, defaultValue) {
532-
if(tinycolor(value).isValid()) return value;
533-
534-
return (defaultValue !== undefined) ?
535-
defaultValue :
536-
attributeDefinition.dflt;
436+
var value = helpers.getValue(trace.textposition, index);
437+
return helpers.coerceEnumerated(attributeTextPosition, value);
537438
}

src/traces/bar/style.js

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,17 @@
1010
'use strict';
1111

1212
var d3 = require('d3');
13+
var Color = require('../../components/color');
1314
var Drawing = require('../../components/drawing');
15+
var Lib = require('../../lib');
1416
var Registry = require('../../registry');
1517

18+
var attributes = require('./attributes'),
19+
attributeTextFont = attributes.textfont,
20+
attributeInsideTextFont = attributes.insidetextfont,
21+
attributeOutsideTextFont = attributes.outsidetextfont;
22+
var helpers = require('./helpers');
23+
1624
function style(gd, cd) {
1725
var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.bars');
1826
var barcount = s.size();
@@ -44,22 +52,116 @@ function style(gd, cd) {
4452

4553
function stylePoints(sel, trace, gd) {
4654
var pts = sel.selectAll('path');
55+
var txs = sel.selectAll('text');
56+
4757
Drawing.pointStyle(pts, trace, gd);
58+
59+
txs.each(function(d) {
60+
var tx = d3.select(this);
61+
var font = determineFont(tx, d, trace, gd);
62+
Drawing.font(tx, font);
63+
});
4864
}
4965

5066
function styleOnSelect(gd, cd) {
5167
var s = cd[0].node3;
5268
var trace = cd[0].trace;
5369

5470
if(trace.selectedpoints) {
55-
Drawing.selectedPointStyle(s.selectAll('path'), trace);
56-
Drawing.selectedTextStyle(s.selectAll('text'), trace);
71+
stylePointsInSelectionMode(s, trace, gd);
5772
} else {
5873
stylePoints(s, trace, gd);
5974
}
6075
}
6176

77+
function stylePointsInSelectionMode(s, trace, gd) {
78+
Drawing.selectedPointStyle(s.selectAll('path'), trace);
79+
styleTextInSelectionMode(s.selectAll('text'), trace, gd);
80+
}
81+
82+
function styleTextInSelectionMode(txs, trace, gd) {
83+
txs.each(function(d) {
84+
var tx = d3.select(this);
85+
var font;
86+
87+
if(d.selected) {
88+
font = Lib.extendFlat({}, determineFont(tx, d, trace, gd));
89+
90+
var selectedFontColor = trace.selected.textfont && trace.selected.textfont.color;
91+
if(selectedFontColor) {
92+
font.color = selectedFontColor;
93+
}
94+
95+
Drawing.font(tx, font);
96+
} else {
97+
Drawing.selectedTextStyle(tx, trace);
98+
}
99+
});
100+
}
101+
102+
function determineFont(tx, d, trace, gd) {
103+
var layoutFont = gd._fullLayout.font;
104+
var textFont = trace.textfont;
105+
106+
if(tx.classed('bartext-inside')) {
107+
var barColor = d.mc;
108+
textFont = getInsideTextFont(trace, d.i, layoutFont, barColor);
109+
} else if(tx.classed('bartext-outside')) {
110+
textFont = getOutsideTextFont(trace, d.i, layoutFont);
111+
}
112+
113+
return textFont;
114+
}
115+
116+
function getTextFont(trace, index, defaultValue) {
117+
return getFontValue(
118+
attributeTextFont, trace.textfont, index, defaultValue);
119+
}
120+
121+
function getInsideTextFont(trace, index, layoutFont, barColor) {
122+
var defaultFont = getTextFont(trace, index, layoutFont);
123+
124+
var wouldFallBackToLayoutFont =
125+
(trace._input.textfont === undefined || trace._input.textfont.color === undefined) ||
126+
(Array.isArray(trace.textfont.color) && trace.textfont.color[index] === undefined);
127+
if(wouldFallBackToLayoutFont) {
128+
defaultFont = {
129+
color: Color.contrast(barColor),
130+
family: defaultFont.family,
131+
size: defaultFont.size
132+
};
133+
}
134+
135+
return getFontValue(
136+
attributeInsideTextFont, trace.insidetextfont, index, defaultFont);
137+
}
138+
139+
function getOutsideTextFont(trace, index, layoutFont) {
140+
var defaultFont = getTextFont(trace, index, layoutFont);
141+
return getFontValue(
142+
attributeOutsideTextFont, trace.outsidetextfont, index, defaultFont);
143+
}
144+
145+
function getFontValue(attributeDefinition, attributeValue, index, defaultValue) {
146+
attributeValue = attributeValue || {};
147+
148+
var familyValue = helpers.getValue(attributeValue.family, index),
149+
sizeValue = helpers.getValue(attributeValue.size, index),
150+
colorValue = helpers.getValue(attributeValue.color, index);
151+
152+
return {
153+
family: helpers.coerceString(
154+
attributeDefinition.family, familyValue, defaultValue.family),
155+
size: helpers.coerceNumber(
156+
attributeDefinition.size, sizeValue, defaultValue.size),
157+
color: helpers.coerceColor(
158+
attributeDefinition.color, colorValue, defaultValue.color)
159+
};
160+
}
161+
62162
module.exports = {
63163
style: style,
64-
styleOnSelect: styleOnSelect
164+
styleOnSelect: styleOnSelect,
165+
getInsideTextFont: getInsideTextFont,
166+
getOutsideTextFont: getOutsideTextFont
65167
};

0 commit comments

Comments
 (0)