Unverified Commit b96ae03b authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Add backgroundColor argument to TextStyle for convenience (#28172)

parent 6f5e88a5
......@@ -14,6 +14,9 @@ const String _kDefaultDebugLabel = 'unknown';
const String _kColorForegroundWarning = 'Cannot provide both a color and a foreground\n'
'The color argument is just a shorthand for "foreground: new Paint()..color = color".';
const String _kColorBackgroundWarning = 'Cannot provide both a backgroundColor and a background\n'
'The backgroundColor argument is just a shorthand for "background: new Paint()..color = color".';
// Examples can assume:
// BuildContext context;
......@@ -60,6 +63,10 @@ const String _kColorForegroundWarning = 'Cannot provide both a color and a foreg
/// If [color] is specified, [foreground] must be null and vice versa. [color] is
/// treated as a shorthand for `Paint()..color = color`.
///
/// If [backgroundColor] is specified, [background] must be null and vice versa.
/// The [backgroundColor] is treated as a shorthand for
/// `background: Paint()..color = backgroundColor`.
///
/// ```dart
/// RichText(
/// text: TextSpan(
......@@ -295,6 +302,7 @@ class TextStyle extends Diagnosticable {
const TextStyle({
this.inherit = true,
this.color,
this.backgroundColor,
this.fontSize,
this.fontWeight,
this.fontStyle,
......@@ -317,7 +325,8 @@ class TextStyle extends Diagnosticable {
_fontFamilyFallback = fontFamilyFallback,
_package = package,
assert(inherit != null),
assert(color == null || foreground == null, _kColorForegroundWarning);
assert(color == null || foreground == null, _kColorForegroundWarning),
assert(backgroundColor == null || background == null, _kColorBackgroundWarning);
/// Whether null values are replaced with their value in an ancestor text
......@@ -338,6 +347,17 @@ class TextStyle extends Diagnosticable {
/// specified in one place, it will dominate [color] in another.
final Color color;
/// The color to use as the background for the text.
///
/// If [background] is specified, this value must be null. The
/// [backgroundColor] property is shorthand for
/// `background: Paint()..color = backgroundColor`.
///
/// In [merge], [apply], and [lerp], conflicts between [backgroundColor] and [background]
/// specification are resolved in [background]'s favor - i.e. if [background] is
/// specified in one place, it will dominate [color] in another.
final Color backgroundColor;
/// The name of the font to use when painting the text (e.g., Roboto). If the
/// font is defined in a package, this will be prefixed with
/// 'packages/package_name/' (e.g. 'packages/cool_fonts/Roboto'). The
......@@ -450,6 +470,15 @@ class TextStyle extends Diagnosticable {
/// styles are created with the same paint settings. Otherwise, each time it
/// will appear like the style changed, which will result in unnecessary
/// updates all the way through the framework.
///
/// If [backgroundColor] is specified, this value must be null. The
/// [backgroundColor] property is shorthand for
/// `background: Paint()..color = backgroundColor`.
///
/// In [merge], [apply], and [lerp], conflicts between [backgroundColor] and
/// [background] specification are resolved in [background]'s favor - i.e. if
/// [background] is specified in one place, it will dominate [backgroundColor]
/// in another.
final Paint background;
/// The decorations to paint near the text (e.g., an underline).
......@@ -488,8 +517,13 @@ class TextStyle extends Diagnosticable {
///
/// One of [color] or [foreground] must be null, and if this has [foreground]
/// specified it will be given preference over any color parameter.
///
/// One of [backgroundColor] or [background] must be null, and if this has
/// [background] specified it will be given preference over any
/// backgroundColor parameter.
TextStyle copyWith({
Color color,
Color backgroundColor,
String fontFamily,
List<String> fontFamilyFallback,
double fontSize,
......@@ -509,6 +543,7 @@ class TextStyle extends Diagnosticable {
String debugLabel,
}) {
assert(color == null || foreground == null, _kColorForegroundWarning);
assert(backgroundColor == null || background == null, _kColorBackgroundWarning);
String newDebugLabel;
assert(() {
if (this.debugLabel != null)
......@@ -518,6 +553,7 @@ class TextStyle extends Diagnosticable {
return TextStyle(
inherit: inherit,
color: this.foreground == null && foreground == null ? color ?? this.color : null,
backgroundColor: this.background == null && background == null ? backgroundColor ?? this.backgroundColor : null,
fontFamily: fontFamily ?? this.fontFamily,
fontFamilyFallback: fontFamilyFallback ?? this.fontFamilyFallback,
fontSize: fontSize ?? this.fontSize,
......@@ -544,7 +580,9 @@ class TextStyle extends Diagnosticable {
/// The non-numeric properties [color], [fontFamily], [decoration],
/// [decorationColor] and [decorationStyle] are replaced with the new values.
///
/// [foreground] will be given preference over [color] if it is not null.
/// [foreground] will be given preference over [color] if it is not null and
/// [background] will be given preference over [backgroundColor] if it is not
/// null.
///
/// The numeric properties are multiplied by the given factors and then
/// incremented by the given deltas.
......@@ -563,9 +601,11 @@ class TextStyle extends Diagnosticable {
/// deltas must not be specified.
///
/// If [foreground] is specified on this object, then applying [color] here
/// will have no effect.
/// will have no effect and if [background] is specified on this object, then
/// applying [backgroundColor] here will have no effect either.
TextStyle apply({
Color color,
Color backgroundColor,
TextDecoration decoration,
Color decorationColor,
TextDecorationStyle decorationStyle,
......@@ -606,6 +646,7 @@ class TextStyle extends Diagnosticable {
return TextStyle(
inherit: inherit,
color: foreground == null ? color ?? this.color : null,
backgroundColor: background == null ? backgroundColor ?? this.backgroundColor : null,
fontFamily: fontFamily ?? this.fontFamily,
fontFamilyFallback: fontFamilyFallback ?? this.fontFamilyFallback,
fontSize: fontSize == null ? null : fontSize * fontSizeFactor + fontSizeDelta,
......@@ -616,7 +657,7 @@ class TextStyle extends Diagnosticable {
textBaseline: textBaseline,
height: height == null ? null : height * heightFactor + heightDelta,
locale: locale,
foreground: foreground != null ? foreground : null,
foreground: foreground,
background: background,
shadows: shadows,
decoration: decoration ?? this.decoration,
......@@ -643,6 +684,10 @@ class TextStyle extends Diagnosticable {
///
/// One of [color] or [foreground] must be null, and if this or `other` has
/// [foreground] specified it will be given preference over any color parameter.
///
/// Similarly, One of [backgroundColor] or [background] must be null, and if
/// this or `other` has [background] specified it will be given preference
/// over any backgroundColor parameter.
TextStyle merge(TextStyle other) {
if (other == null)
return this;
......@@ -658,6 +703,7 @@ class TextStyle extends Diagnosticable {
return copyWith(
color: other.color,
backgroundColor: other.backgroundColor,
fontFamily: other.fontFamily,
fontFamilyFallback: other.fontFamilyFallback,
fontSize: other.fontSize,
......@@ -687,6 +733,10 @@ class TextStyle extends Diagnosticable {
/// If [foreground] is specified on either of `a` or `b`, both will be treated
/// as if they have a [foreground] paint (creating a new [Paint] if necessary
/// based on the [color] property).
///
/// If [background] is specified on either of `a` or `b`, both will be treated
/// as if they have a [background] paint (creating a new [Paint] if necessary
/// based on the [backgroundColor] property).
static TextStyle lerp(TextStyle a, TextStyle b, double t) {
assert(t != null);
assert(a == null || b == null || a.inherit == b.inherit);
......@@ -704,6 +754,7 @@ class TextStyle extends Diagnosticable {
return TextStyle(
inherit: b.inherit,
color: Color.lerp(null, b.color, t),
backgroundColor: Color.lerp(null, b.backgroundColor, t),
fontFamily: t < 0.5 ? null : b.fontFamily,
fontFamilyFallback: t < 0.5 ? null : b.fontFamilyFallback,
fontSize: t < 0.5 ? null : b.fontSize,
......@@ -728,6 +779,7 @@ class TextStyle extends Diagnosticable {
return TextStyle(
inherit: a.inherit,
color: Color.lerp(a.color, null, t),
backgroundColor: Color.lerp(null, a.backgroundColor, t),
fontFamily: t < 0.5 ? a.fontFamily : null,
fontFamilyFallback: t < 0.5 ? a.fontFamilyFallback : null,
fontSize: t < 0.5 ? a.fontSize : null,
......@@ -751,6 +803,7 @@ class TextStyle extends Diagnosticable {
return TextStyle(
inherit: b.inherit,
color: a.foreground == null && b.foreground == null ? Color.lerp(a.color, b.color, t) : null,
backgroundColor: a.background == null && b.background == null ? Color.lerp(a.backgroundColor, b.backgroundColor, t) : null,
fontFamily: t < 0.5 ? a.fontFamily : b.fontFamily,
fontFamilyFallback: t < 0.5 ? a.fontFamilyFallback : b.fontFamilyFallback,
fontSize: ui.lerpDouble(a.fontSize ?? b.fontSize, b.fontSize ?? a.fontSize, t),
......@@ -766,7 +819,11 @@ class TextStyle extends Diagnosticable {
? a.foreground ?? (Paint()..color = a.color)
: b.foreground ?? (Paint()..color = b.color)
: null,
background: t < 0.5 ? a.background : b.background,
background: (a.background != null || b.background != null)
? t < 0.5
? a.background ?? (Paint()..color = a.backgroundColor)
: b.background ?? (Paint()..color = b.backgroundColor)
: null,
shadows: t < 0.5 ? a.shadows : b.shadows,
decoration: t < 0.5 ? a.decoration : b.decoration,
decorationColor: Color.lerp(a.decorationColor, b.decorationColor, t),
......@@ -793,7 +850,10 @@ class TextStyle extends Diagnosticable {
height: height,
locale: locale,
foreground: foreground,
background: background,
background: background ?? (backgroundColor != null
? (Paint()..color = backgroundColor)
: null
),
shadows: shadows,
);
}
......@@ -873,6 +933,7 @@ class TextStyle extends Diagnosticable {
!listEquals(fontFamilyFallback, other.fontFamilyFallback))
return RenderComparison.layout;
if (color != other.color ||
backgroundColor != other.backgroundColor ||
decoration != other.decoration ||
decorationColor != other.decorationColor ||
decorationStyle != other.decorationStyle)
......@@ -889,6 +950,7 @@ class TextStyle extends Diagnosticable {
final TextStyle typedOther = other;
return inherit == typedOther.inherit &&
color == typedOther.color &&
backgroundColor == typedOther.backgroundColor &&
fontFamily == typedOther.fontFamily &&
fontSize == typedOther.fontSize &&
fontWeight == typedOther.fontWeight &&
......@@ -912,6 +974,7 @@ class TextStyle extends Diagnosticable {
return hashValues(
inherit,
color,
backgroundColor,
fontFamily,
fontFamilyFallback,
fontSize,
......@@ -942,6 +1005,7 @@ class TextStyle extends Diagnosticable {
properties.add(MessageProperty('${prefix}debugLabel', debugLabel));
final List<DiagnosticsNode> styles = <DiagnosticsNode>[];
styles.add(DiagnosticsProperty<Color>('${prefix}color', color, defaultValue: null));
styles.add(DiagnosticsProperty<Color>('${prefix}backgroundColor', backgroundColor, defaultValue: null));
styles.add(StringProperty('${prefix}family', fontFamily, defaultValue: null, quoted: false));
styles.add(IterableProperty<String>('${prefix}familyFallback', fontFamilyFallback, defaultValue: null));
styles.add(DoubleProperty('${prefix}size', fontSize, defaultValue: null));
......
......@@ -666,6 +666,7 @@ class _TextStyleProxy implements TextStyle {
// Do make sure that all the properties correctly forward to the _delegate.
@override Color get color => _delegate.color;
@override Color get backgroundColor => _delegate.backgroundColor;
@override String get debugLabel => _delegate.debugLabel;
@override TextDecoration get decoration => _delegate.decoration;
@override Color get decorationColor => _delegate.decorationColor;
......@@ -700,7 +701,7 @@ class _TextStyleProxy implements TextStyle {
}
@override
TextStyle apply({ Color color, TextDecoration decoration, Color decorationColor, TextDecorationStyle decorationStyle, String fontFamily, List<String> fontFamilyFallback, double fontSizeFactor = 1.0, double fontSizeDelta = 0.0, int fontWeightDelta = 0, double letterSpacingFactor = 1.0, double letterSpacingDelta = 0.0, double wordSpacingFactor = 1.0, double wordSpacingDelta = 0.0, double heightFactor = 1.0, double heightDelta = 0.0 }) {
TextStyle apply({ Color color, Color backgroundColor, TextDecoration decoration, Color decorationColor, TextDecorationStyle decorationStyle, String fontFamily, List<String> fontFamilyFallback, double fontSizeFactor = 1.0, double fontSizeDelta = 0.0, int fontWeightDelta = 0, double letterSpacingFactor = 1.0, double letterSpacingDelta = 0.0, double wordSpacingFactor = 1.0, double wordSpacingDelta = 0.0, double heightFactor = 1.0, double heightDelta = 0.0 }) {
throw UnimplementedError();
}
......@@ -710,7 +711,7 @@ class _TextStyleProxy implements TextStyle {
}
@override
TextStyle copyWith({ Color color, String fontFamily, List<String> fontFamilyFallback, double fontSize, FontWeight fontWeight, FontStyle fontStyle, double letterSpacing, double wordSpacing, TextBaseline textBaseline, double height, Locale locale, ui.Paint foreground, ui.Paint background, List<Shadow> shadows, TextDecoration decoration, Color decorationColor, TextDecorationStyle decorationStyle, String debugLabel }) {
TextStyle copyWith({ Color color, Color backgroundColor, String fontFamily, List<String> fontFamilyFallback, double fontSize, FontWeight fontWeight, FontStyle fontStyle, double letterSpacing, double wordSpacing, TextBaseline textBaseline, double height, Locale locale, ui.Paint foreground, ui.Paint background, List<Shadow> shadows, TextDecoration decoration, Color decorationColor, TextDecorationStyle decorationStyle, String debugLabel }) {
throw UnimplementedError();
}
......
......@@ -294,4 +294,58 @@ void main() {
expect(TextStyle.lerp(redPaintTextStyle, bluePaintTextStyle, .25).foreground.color, red);
expect(TextStyle.lerp(redPaintTextStyle, bluePaintTextStyle, .75).foreground.color, blue);
});
test('backgroundColor', () {
const TextStyle s1 = TextStyle();
expect(s1.backgroundColor, isNull);
expect(s1.toString(), 'TextStyle(<all styles inherited>)');
const TextStyle s2 = TextStyle(backgroundColor: Color(0xFF00FF00));
expect(s2.backgroundColor, const Color(0xFF00FF00));
expect(s2.toString(), 'TextStyle(inherit: true, backgroundColor: Color(0xff00ff00))');
final ui.TextStyle ts2 = s2.getTextStyle();
expect(ts2.toString(), contains('background: Paint(Color(0xff00ff00))'));
});
test('TextStyle background and backgroundColor combos', () {
const Color red = Color.fromARGB(255, 255, 0, 0);
const Color blue = Color.fromARGB(255, 0, 0, 255);
const TextStyle redTextStyle = TextStyle(backgroundColor: red);
const TextStyle blueTextStyle = TextStyle(backgroundColor: blue);
final TextStyle redPaintTextStyle = TextStyle(background: Paint()..color = red);
final TextStyle bluePaintTextStyle = TextStyle(background: Paint()..color = blue);
// merge/copyWith
final TextStyle redBlueBothForegroundMerged = redTextStyle.merge(blueTextStyle);
expect(redBlueBothForegroundMerged.backgroundColor, blue);
expect(redBlueBothForegroundMerged.foreground, isNull);
final TextStyle redBlueBothPaintMerged = redPaintTextStyle.merge(bluePaintTextStyle);
expect(redBlueBothPaintMerged.backgroundColor, null);
expect(redBlueBothPaintMerged.background, bluePaintTextStyle.background);
final TextStyle redPaintBlueColorMerged = redPaintTextStyle.merge(blueTextStyle);
expect(redPaintBlueColorMerged.backgroundColor, null);
expect(redPaintBlueColorMerged.background, redPaintTextStyle.background);
final TextStyle blueColorRedPaintMerged = blueTextStyle.merge(redPaintTextStyle);
expect(blueColorRedPaintMerged.backgroundColor, null);
expect(blueColorRedPaintMerged.background, redPaintTextStyle.background);
// apply
expect(redPaintTextStyle.apply(backgroundColor: blue).backgroundColor, isNull);
expect(redPaintTextStyle.apply(backgroundColor: blue).background.color, red);
expect(redTextStyle.apply(backgroundColor: blue).backgroundColor, blue);
// lerp
expect(TextStyle.lerp(redTextStyle, blueTextStyle, .25).backgroundColor, Color.lerp(red, blue, .25));
expect(TextStyle.lerp(redTextStyle, bluePaintTextStyle, .25).backgroundColor, isNull);
expect(TextStyle.lerp(redTextStyle, bluePaintTextStyle, .25).background.color, red);
expect(TextStyle.lerp(redTextStyle, bluePaintTextStyle, .75).background.color, blue);
expect(TextStyle.lerp(redPaintTextStyle, bluePaintTextStyle, .25).backgroundColor, isNull);
expect(TextStyle.lerp(redPaintTextStyle, bluePaintTextStyle, .25).background.color, red);
expect(TextStyle.lerp(redPaintTextStyle, bluePaintTextStyle, .75).background.color, blue);
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment