Commit 67d16cd5 authored by Yegor's avatar Yegor Committed by GitHub

Theme.of provides all TextStyle properties (#12552)

* Theme provides all TextStyle properties

* match field declaration order in the test

* Theme.of returns text style with inherit == false

* change TextStyle.inherit logic; docs

* add TextStyle.debugLabel

* address comments

* add debug labels to Typography text styles
parent faf44b59
......@@ -101,12 +101,16 @@ abstract class MaterialLocalizations {
///
/// This text theme is incomplete. For example, it lacks text color
/// information. This theme must be merged with another text theme that
/// provides the missing values. The text styles provided by this theme have
/// their [TextStyle.inherit] property set to true.
/// provides the missing values.
///
/// Typically a complete theme is obtained via [Theme.of], which can be
/// localized using the [Localizations] widget.
///
/// The text styles provided by this theme are expected to have their
/// [TextStyle.inherit] property set to false, so that the [ThemeData]
/// obtained from [Theme.of] no longer inherits text style properties and
/// contains a complete set of properties needed to style a [Text] widget.
///
/// See also: https://material.io/guidelines/style/typography.html
TextTheme get localTextGeometry;
......
......@@ -462,11 +462,13 @@ class ThemeData {
/// Caches localized themes to speed up the [localize] method.
static final _FifoCache<_IdentityThemeDataCacheKey, ThemeData> _localizedThemeDataCache = new _FifoCache<_IdentityThemeDataCacheKey, ThemeData>(_localizedThemeDataCacheSize);
/// Returns a new theme built by merging [baseTheme] into the text geometry
/// provided by the [localTextGeometry].
/// Returns a new theme built by merging the text geometry provided by the
/// [localTextGeometry] theme with the [baseTheme].
///
/// The [TextStyle.inherit] field in the text styles provided by
/// [localTextGeometry] must be set to true.
/// For those text styles in the [baseTheme] whose [TextStyle.inherit] is set
/// to true, the returned theme's text styles inherit the geometric properties
/// of [localTextGeometry]. The resulting text styles' [TextStyle.inherit] is
/// set to those provided by [localTextGeometry].
static ThemeData localize(ThemeData baseTheme, TextTheme localTextGeometry) {
// WARNING: this method memoizes the result in a cache based on the
// previously seen baseTheme and localTextGeometry. Memoization is safe
......
......@@ -134,6 +134,11 @@ class TextTheme {
/// Creates a new [TextTheme] where each text style from this object has been
/// merged with the matching text style from the `other` object.
///
/// The merging is done by calling [TextStyle.merge] on each respective pair
/// of text styles from this and the [other] text themes and is subject to
/// the value of [TextStyle.inherit] flag. For more details, see the
/// documentation on [TextStyle.merge] and [TextStyle.inherit].
///
/// This is particularly useful if one [TextTheme] defines one set of
/// properties and another defines a different set, e.g. having colors defined
/// in one text theme and font sizes in another.
......@@ -170,71 +175,107 @@ class TextTheme {
double fontSizeFactor: 1.0,
double fontSizeDelta: 0.0,
Color displayColor,
Color bodyColor
Color bodyColor,
TextDecoration decoration,
Color decorationColor,
TextDecorationStyle decorationStyle,
}) {
return new TextTheme(
display4: display4.apply(
color: displayColor,
decoration: decoration,
decorationColor: decorationColor,
decorationStyle: decorationStyle,
fontFamily: fontFamily,
fontSizeFactor: fontSizeFactor,
fontSizeDelta: fontSizeDelta,
),
display3: display3.apply(
color: displayColor,
decoration: decoration,
decorationColor: decorationColor,
decorationStyle: decorationStyle,
fontFamily: fontFamily,
fontSizeFactor: fontSizeFactor,
fontSizeDelta: fontSizeDelta,
),
display2: display2.apply(
color: displayColor,
decoration: decoration,
decorationColor: decorationColor,
decorationStyle: decorationStyle,
fontFamily: fontFamily,
fontSizeFactor: fontSizeFactor,
fontSizeDelta: fontSizeDelta,
),
display1: display1.apply(
color: displayColor,
decoration: decoration,
decorationColor: decorationColor,
decorationStyle: decorationStyle,
fontFamily: fontFamily,
fontSizeFactor: fontSizeFactor,
fontSizeDelta: fontSizeDelta,
),
headline: headline.apply(
color: bodyColor,
decoration: decoration,
decorationColor: decorationColor,
decorationStyle: decorationStyle,
fontFamily: fontFamily,
fontSizeFactor: fontSizeFactor,
fontSizeDelta: fontSizeDelta,
),
title: title.apply(
color: bodyColor,
decoration: decoration,
decorationColor: decorationColor,
decorationStyle: decorationStyle,
fontFamily: fontFamily,
fontSizeFactor: fontSizeFactor,
fontSizeDelta: fontSizeDelta,
),
subhead: subhead.apply(
color: bodyColor,
decoration: decoration,
decorationColor: decorationColor,
decorationStyle: decorationStyle,
fontFamily: fontFamily,
fontSizeFactor: fontSizeFactor,
fontSizeDelta: fontSizeDelta,
),
body2: body2.apply(
color: bodyColor,
decoration: decoration,
decorationColor: decorationColor,
decorationStyle: decorationStyle,
fontFamily: fontFamily,
fontSizeFactor: fontSizeFactor,
fontSizeDelta: fontSizeDelta,
),
body1: body1.apply(
color: bodyColor,
decoration: decoration,
decorationColor: decorationColor,
decorationStyle: decorationStyle,
fontFamily: fontFamily,
fontSizeFactor: fontSizeFactor,
fontSizeDelta: fontSizeDelta,
),
caption: caption.apply(
color: displayColor,
decoration: decoration,
decorationColor: decorationColor,
decorationStyle: decorationStyle,
fontFamily: fontFamily,
fontSizeFactor: fontSizeFactor,
fontSizeDelta: fontSizeDelta,
),
button: button.apply(
color: bodyColor,
decoration: decoration,
decorationColor: decorationColor,
decorationStyle: decorationStyle,
fontFamily: fontFamily,
fontSizeFactor: fontSizeFactor,
fontSizeDelta: fontSizeDelta,
......@@ -353,59 +394,59 @@ class Typography {
// TODO(yjbanov): implement font fallback (see "Font stack" at https://material.io/guidelines/style/typography.html)
class _MaterialTextColorThemes {
static const TextTheme blackMountainView = const TextTheme(
display4: const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.black54),
display3: const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.black54),
display2: const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.black54),
display1: const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.black54),
headline: const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.black87),
title : const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.black87),
subhead : const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.black87),
body2 : const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.black87),
body1 : const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.black87),
caption : const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.black54),
button : const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.black87),
display4: const TextStyle(debugLabel: 'blackMountainView display4', fontFamily: 'Roboto', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
display3: const TextStyle(debugLabel: 'blackMountainView display3', fontFamily: 'Roboto', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
display2: const TextStyle(debugLabel: 'blackMountainView display2', fontFamily: 'Roboto', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
display1: const TextStyle(debugLabel: 'blackMountainView display1', fontFamily: 'Roboto', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
headline: const TextStyle(debugLabel: 'blackMountainView headline', fontFamily: 'Roboto', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
title : const TextStyle(debugLabel: 'blackMountainView title', fontFamily: 'Roboto', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
subhead : const TextStyle(debugLabel: 'blackMountainView subhead', fontFamily: 'Roboto', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
body2 : const TextStyle(debugLabel: 'blackMountainView body2', fontFamily: 'Roboto', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
body1 : const TextStyle(debugLabel: 'blackMountainView body1', fontFamily: 'Roboto', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
caption : const TextStyle(debugLabel: 'blackMountainView caption', fontFamily: 'Roboto', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
button : const TextStyle(debugLabel: 'blackMountainView button', fontFamily: 'Roboto', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
);
static const TextTheme whiteMountainView = const TextTheme(
display4: const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.white70),
display3: const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.white70),
display2: const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.white70),
display1: const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.white70),
headline: const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.white),
title : const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.white),
subhead : const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.white),
body2 : const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.white),
body1 : const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.white),
caption : const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.white70),
button : const TextStyle(fontFamily: 'Roboto', inherit: true, color: Colors.white),
display4: const TextStyle(debugLabel: 'whiteMountainView display4', fontFamily: 'Roboto', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
display3: const TextStyle(debugLabel: 'whiteMountainView display3', fontFamily: 'Roboto', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
display2: const TextStyle(debugLabel: 'whiteMountainView display2', fontFamily: 'Roboto', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
display1: const TextStyle(debugLabel: 'whiteMountainView display1', fontFamily: 'Roboto', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
headline: const TextStyle(debugLabel: 'whiteMountainView headline', fontFamily: 'Roboto', inherit: true, color: Colors.white, decoration: TextDecoration.none),
title : const TextStyle(debugLabel: 'whiteMountainView title', fontFamily: 'Roboto', inherit: true, color: Colors.white, decoration: TextDecoration.none),
subhead : const TextStyle(debugLabel: 'whiteMountainView subhead', fontFamily: 'Roboto', inherit: true, color: Colors.white, decoration: TextDecoration.none),
body2 : const TextStyle(debugLabel: 'whiteMountainView body2', fontFamily: 'Roboto', inherit: true, color: Colors.white, decoration: TextDecoration.none),
body1 : const TextStyle(debugLabel: 'whiteMountainView body1', fontFamily: 'Roboto', inherit: true, color: Colors.white, decoration: TextDecoration.none),
caption : const TextStyle(debugLabel: 'whiteMountainView caption', fontFamily: 'Roboto', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
button : const TextStyle(debugLabel: 'whiteMountainView button', fontFamily: 'Roboto', inherit: true, color: Colors.white, decoration: TextDecoration.none),
);
static const TextTheme blackCupertino = const TextTheme(
display4: const TextStyle(fontFamily: '.SF UI Display', inherit: true, color: Colors.black54),
display3: const TextStyle(fontFamily: '.SF UI Display', inherit: true, color: Colors.black54),
display2: const TextStyle(fontFamily: '.SF UI Display', inherit: true, color: Colors.black54),
display1: const TextStyle(fontFamily: '.SF UI Display', inherit: true, color: Colors.black54),
headline: const TextStyle(fontFamily: '.SF UI Display', inherit: true, color: Colors.black87),
title : const TextStyle(fontFamily: '.SF UI Display', inherit: true, color: Colors.black87),
subhead : const TextStyle(fontFamily: '.SF UI Text', inherit: true, color: Colors.black87),
body2 : const TextStyle(fontFamily: '.SF UI Text', inherit: true, color: Colors.black87),
body1 : const TextStyle(fontFamily: '.SF UI Text', inherit: true, color: Colors.black87),
caption : const TextStyle(fontFamily: '.SF UI Text', inherit: true, color: Colors.black54),
button : const TextStyle(fontFamily: '.SF UI Text', inherit: true, color: Colors.black87),
display4: const TextStyle(debugLabel: 'blackCupertino display4', fontFamily: '.SF UI Display', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
display3: const TextStyle(debugLabel: 'blackCupertino display3', fontFamily: '.SF UI Display', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
display2: const TextStyle(debugLabel: 'blackCupertino display2', fontFamily: '.SF UI Display', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
display1: const TextStyle(debugLabel: 'blackCupertino display1', fontFamily: '.SF UI Display', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
headline: const TextStyle(debugLabel: 'blackCupertino headline', fontFamily: '.SF UI Display', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
title : const TextStyle(debugLabel: 'blackCupertino title', fontFamily: '.SF UI Display', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
subhead : const TextStyle(debugLabel: 'blackCupertino subhead', fontFamily: '.SF UI Text', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
body2 : const TextStyle(debugLabel: 'blackCupertino body2', fontFamily: '.SF UI Text', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
body1 : const TextStyle(debugLabel: 'blackCupertino body1', fontFamily: '.SF UI Text', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
caption : const TextStyle(debugLabel: 'blackCupertino caption', fontFamily: '.SF UI Text', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
button : const TextStyle(debugLabel: 'blackCupertino button', fontFamily: '.SF UI Text', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
);
static const TextTheme whiteCupertino = const TextTheme(
display4: const TextStyle(fontFamily: '.SF UI Display', inherit: true, color: Colors.white70),
display3: const TextStyle(fontFamily: '.SF UI Display', inherit: true, color: Colors.white70),
display2: const TextStyle(fontFamily: '.SF UI Display', inherit: true, color: Colors.white70),
display1: const TextStyle(fontFamily: '.SF UI Display', inherit: true, color: Colors.white70),
headline: const TextStyle(fontFamily: '.SF UI Display', inherit: true, color: Colors.white),
title : const TextStyle(fontFamily: '.SF UI Display', inherit: true, color: Colors.white),
subhead : const TextStyle(fontFamily: '.SF UI Text', inherit: true, color: Colors.white),
body2 : const TextStyle(fontFamily: '.SF UI Text', inherit: true, color: Colors.white),
body1 : const TextStyle(fontFamily: '.SF UI Text', inherit: true, color: Colors.white),
caption : const TextStyle(fontFamily: '.SF UI Text', inherit: true, color: Colors.white70),
button : const TextStyle(fontFamily: '.SF UI Text', inherit: true, color: Colors.white),
display4: const TextStyle(debugLabel: 'whiteCupertino display4', fontFamily: '.SF UI Display', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
display3: const TextStyle(debugLabel: 'whiteCupertino display3', fontFamily: '.SF UI Display', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
display2: const TextStyle(debugLabel: 'whiteCupertino display2', fontFamily: '.SF UI Display', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
display1: const TextStyle(debugLabel: 'whiteCupertino display1', fontFamily: '.SF UI Display', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
headline: const TextStyle(debugLabel: 'whiteCupertino headline', fontFamily: '.SF UI Display', inherit: true, color: Colors.white, decoration: TextDecoration.none),
title : const TextStyle(debugLabel: 'whiteCupertino title', fontFamily: '.SF UI Display', inherit: true, color: Colors.white, decoration: TextDecoration.none),
subhead : const TextStyle(debugLabel: 'whiteCupertino subhead', fontFamily: '.SF UI Text', inherit: true, color: Colors.white, decoration: TextDecoration.none),
body2 : const TextStyle(debugLabel: 'whiteCupertino body2', fontFamily: '.SF UI Text', inherit: true, color: Colors.white, decoration: TextDecoration.none),
body1 : const TextStyle(debugLabel: 'whiteCupertino body1', fontFamily: '.SF UI Text', inherit: true, color: Colors.white, decoration: TextDecoration.none),
caption : const TextStyle(debugLabel: 'whiteCupertino caption', fontFamily: '.SF UI Text', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
button : const TextStyle(debugLabel: 'whiteCupertino button', fontFamily: '.SF UI Text', inherit: true, color: Colors.white, decoration: TextDecoration.none),
);
}
......@@ -444,46 +485,46 @@ class MaterialTextGeometry {
/// Defines text geometry for English-like scripts, such as English, French, Russian, etc.
static const TextTheme englishLike = const TextTheme(
display4: const TextStyle(fontSize: 112.0, fontWeight: FontWeight.w100, textBaseline: TextBaseline.alphabetic),
display3: const TextStyle(fontSize: 56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
display2: const TextStyle(fontSize: 45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
display1: const TextStyle(fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
headline: const TextStyle(fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
title : const TextStyle(fontSize: 20.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
subhead : const TextStyle(fontSize: 16.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
body2 : const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
body1 : const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
caption : const TextStyle(fontSize: 12.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
button : const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
display4: const TextStyle(debugLabel: 'englishLike display4', inherit: false, fontSize: 112.0, fontWeight: FontWeight.w100, textBaseline: TextBaseline.alphabetic),
display3: const TextStyle(debugLabel: 'englishLike display3', inherit: false, fontSize: 56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
display2: const TextStyle(debugLabel: 'englishLike display2', inherit: false, fontSize: 45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
display1: const TextStyle(debugLabel: 'englishLike display1', inherit: false, fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
headline: const TextStyle(debugLabel: 'englishLike headline', inherit: false, fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
title : const TextStyle(debugLabel: 'englishLike title', inherit: false, fontSize: 20.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
subhead : const TextStyle(debugLabel: 'englishLike subhead', inherit: false, fontSize: 16.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
body2 : const TextStyle(debugLabel: 'englishLike body2', inherit: false, fontSize: 14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
body1 : const TextStyle(debugLabel: 'englishLike body1', inherit: false, fontSize: 14.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
caption : const TextStyle(debugLabel: 'englishLike caption', inherit: false, fontSize: 12.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
button : const TextStyle(debugLabel: 'englishLike button', inherit: false, fontSize: 14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
);
/// Defines text geometry for dense scripts, such as Chinese, Japanese, Korean, etc.
static const TextTheme dense = const TextTheme(
display4: const TextStyle(fontSize: 112.0, fontWeight: FontWeight.w100, textBaseline: TextBaseline.ideographic),
display3: const TextStyle(fontSize: 56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
display2: const TextStyle(fontSize: 45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
display1: const TextStyle(fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
headline: const TextStyle(fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
title : const TextStyle(fontSize: 21.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
subhead : const TextStyle(fontSize: 17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
body2 : const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
body1 : const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
caption : const TextStyle(fontSize: 13.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
button : const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
display4: const TextStyle(debugLabel: 'dense display4', inherit: false, fontSize: 112.0, fontWeight: FontWeight.w100, textBaseline: TextBaseline.ideographic),
display3: const TextStyle(debugLabel: 'dense display3', inherit: false, fontSize: 56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
display2: const TextStyle(debugLabel: 'dense display2', inherit: false, fontSize: 45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
display1: const TextStyle(debugLabel: 'dense display1', inherit: false, fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
headline: const TextStyle(debugLabel: 'dense headline', inherit: false, fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
title : const TextStyle(debugLabel: 'dense title', inherit: false, fontSize: 21.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
subhead : const TextStyle(debugLabel: 'dense subhead', inherit: false, fontSize: 17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
body2 : const TextStyle(debugLabel: 'dense body2', inherit: false, fontSize: 15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
body1 : const TextStyle(debugLabel: 'dense body1', inherit: false, fontSize: 15.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
caption : const TextStyle(debugLabel: 'dense caption', inherit: false, fontSize: 13.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
button : const TextStyle(debugLabel: 'dense button', inherit: false, fontSize: 15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
);
/// Defines text geometry for tall scripts, such as Farsi, Hindi, Thai, etc.
static const TextTheme tall = const TextTheme(
display4: const TextStyle(fontSize: 112.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
display3: const TextStyle(fontSize: 56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
display2: const TextStyle(fontSize: 45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
display1: const TextStyle(fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
headline: const TextStyle(fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
title : const TextStyle(fontSize: 21.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
subhead : const TextStyle(fontSize: 17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
body2 : const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
body1 : const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
caption : const TextStyle(fontSize: 13.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
button : const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
display4: const TextStyle(debugLabel: 'tall display4', inherit: false, fontSize: 112.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
display3: const TextStyle(debugLabel: 'tall display3', inherit: false, fontSize: 56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
display2: const TextStyle(debugLabel: 'tall display2', inherit: false, fontSize: 45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
display1: const TextStyle(debugLabel: 'tall display1', inherit: false, fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
headline: const TextStyle(debugLabel: 'tall headline', inherit: false, fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
title : const TextStyle(debugLabel: 'tall title', inherit: false, fontSize: 21.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
subhead : const TextStyle(debugLabel: 'tall subhead', inherit: false, fontSize: 17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
body2 : const TextStyle(debugLabel: 'tall body2', inherit: false, fontSize: 15.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
body1 : const TextStyle(debugLabel: 'tall body1', inherit: false, fontSize: 15.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
caption : const TextStyle(debugLabel: 'tall caption', inherit: false, fontSize: 13.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
button : const TextStyle(debugLabel: 'tall button', inherit: false, fontSize: 15.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
);
}
......@@ -8,6 +8,8 @@ import 'package:flutter/foundation.dart';
import 'basic_types.dart';
const String _kDefaultDebugLabel = 'unknown';
/// An immutable style in which paint text.
///
/// ## Sample code
......@@ -230,6 +232,7 @@ class TextStyle extends Diagnosticable {
this.decoration,
this.decorationColor,
this.decorationStyle,
this.debugLabel,
String fontFamily,
String package,
}) : fontFamily = package == null ? fontFamily : 'packages/$package/$fontFamily',
......@@ -302,6 +305,19 @@ class TextStyle extends Diagnosticable {
/// The style in which to paint the text decorations (e.g., dashed).
final TextDecorationStyle decorationStyle;
/// A human-readable description of this text style.
///
/// This property is maintained only in debug builds.
///
/// When merging ([merge]), copying ([copyWith]), modifying using [apply], or
/// interpolating ([lerp]), the label of the resulting style is marked with
/// the debug labels of the original styles. This helps figuring out where a
/// particular text style came from.
///
/// This property is not considered when comparing text styles using `==` or
/// [compareTo], and it does not affect [hashCode].
final String debugLabel;
/// Creates a copy of this text style but with the given fields replaced with
/// the new values.
TextStyle copyWith({
......@@ -317,7 +333,14 @@ class TextStyle extends Diagnosticable {
TextDecoration decoration,
Color decorationColor,
TextDecorationStyle decorationStyle,
String debugLabel,
}) {
String newDebugLabel;
assert(() {
if (this.debugLabel != null)
newDebugLabel = debugLabel ?? 'copy of ${this.debugLabel}';
return true;
}());
return new TextStyle(
inherit: inherit,
color: color ?? this.color,
......@@ -332,11 +355,18 @@ class TextStyle extends Diagnosticable {
decoration: decoration ?? this.decoration,
decorationColor: decorationColor ?? this.decorationColor,
decorationStyle: decorationStyle ?? this.decorationStyle,
debugLabel: newDebugLabel,
);
}
/// Creates a copy of this text style but with the numeric fields multiplied
/// by the given factors and then incremented by the given deltas.
/// Creates a copy of this text style replacing or altering the specified
/// properties.
///
/// The non-numeric properties [color], [fontFamily], [decoration],
/// [decorationColor] and [decorationStyle] are replaced with the new values.
///
/// The numeric properties are multiplied by the given factors and then
/// incremented by the given deltas.
///
/// For example, `style.apply(fontSizeFactor: 2.0, fontSizeDelta: 1.0)` would
/// return a [TextStyle] whose [fontSize] is `style.fontSize * 2.0 + 1.0`.
......@@ -346,14 +376,15 @@ class TextStyle extends Diagnosticable {
/// applied to a `style` whose [fontWeight] is [FontWeight.w500] will return a
/// [TextStyle] with a [FontWeight.w300].
///
/// The arguments must not be null.
/// The numeric arguments must not be null.
///
/// If the underlying values are null, then the corresponding factors and/or
/// deltas must not be specified.
///
/// The non-numeric fields can be controlled using the corresponding arguments.
TextStyle apply({
Color color,
TextDecoration decoration,
Color decorationColor,
TextDecorationStyle decorationStyle,
String fontFamily,
double fontSizeFactor: 1.0,
double fontSizeDelta: 0.0,
......@@ -379,6 +410,14 @@ class TextStyle extends Diagnosticable {
assert(heightFactor != null);
assert(heightDelta != null);
assert(heightFactor != null || (heightFactor == 1.0 && heightDelta == 0.0));
String modifiedDebugLabel;
assert(() {
if (debugLabel != null)
modifiedDebugLabel = 'modified $debugLabel';
return true;
}());
return new TextStyle(
inherit: inherit,
color: color ?? this.color,
......@@ -390,19 +429,40 @@ class TextStyle extends Diagnosticable {
wordSpacing: wordSpacing == null ? null : wordSpacing * wordSpacingFactor + wordSpacingDelta,
textBaseline: textBaseline,
height: height == null ? null : height * heightFactor + heightDelta,
decoration: decoration,
decorationColor: decorationColor,
decorationStyle: decorationStyle,
decoration: decoration ?? this.decoration,
decorationColor: decorationColor ?? this.decorationColor,
decorationStyle: decorationStyle ?? this.decorationStyle,
debugLabel: modifiedDebugLabel,
);
}
/// Returns a new text style that matches this text style but with some values
/// replaced by the non-null parameters of the given text style. If the given
/// text style is null, simply returns this text style.
/// Returns a new text style that is a combination of this style and the given
/// [other] style.
///
/// If the given [other] text style has its [TextStyle.inherit] set to true,
/// its null properties are replaced with the non-null properties of this text
/// style. The [other] style _inherits_ the properties of this style. Another
/// way to think of it is that the "missing" properties of the [other] style
/// are _filled_ by the properties of this style.
///
/// If the given [other] text style has its [TextStyle.inherit] set to false,
/// returns the given [other] style unchanged. The [other] style does not
/// inherit properties of this style.
///
/// If the given text style is null, returns this text style.
TextStyle merge(TextStyle other) {
if (other == null)
return this;
assert(other.inherit);
if (!other.inherit)
return other;
String mergedDebugLabel;
assert(() {
if (other.debugLabel != null || debugLabel != null)
mergedDebugLabel = '${other.debugLabel ?? _kDefaultDebugLabel} < ${debugLabel ?? _kDefaultDebugLabel}';
return true;
}());
return copyWith(
color: other.color,
fontFamily: other.fontFamily,
......@@ -415,7 +475,8 @@ class TextStyle extends Diagnosticable {
height: other.height,
decoration: other.decoration,
decorationColor: other.decorationColor,
decorationStyle: other.decorationStyle
decorationStyle: other.decorationStyle,
debugLabel: mergedDebugLabel,
);
}
......@@ -424,6 +485,13 @@ class TextStyle extends Diagnosticable {
/// This will not work well if the styles don't set the same fields.
static TextStyle lerp(TextStyle begin, TextStyle end, double t) {
assert(begin.inherit == end.inherit);
String lerpDebugLabel;
assert(() {
lerpDebugLabel = 'lerp(${begin.debugLabel ?? _kDefaultDebugLabel}, ${end.debugLabel ?? _kDefaultDebugLabel})';
return true;
}());
return new TextStyle(
inherit: end.inherit,
color: Color.lerp(begin.color, end.color, t),
......@@ -437,7 +505,8 @@ class TextStyle extends Diagnosticable {
height: ui.lerpDouble(begin.height ?? end.height, end.height ?? begin.height, t),
decoration: t < 0.5 ? begin.decoration : end.decoration,
decorationColor: Color.lerp(begin.decorationColor, end.decorationColor, t),
decorationStyle: t < 0.5 ? begin.decorationStyle : end.decorationStyle
decorationStyle: t < 0.5 ? begin.decorationStyle : end.decorationStyle,
debugLabel: lerpDebugLabel,
);
}
......@@ -564,6 +633,8 @@ class TextStyle extends Diagnosticable {
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties, { String prefix: '' }) {
super.debugFillProperties(properties);
if (debugLabel != null)
properties.add(new MessageProperty('${prefix}debugLabel', debugLabel));
final List<DiagnosticsNode> styles = <DiagnosticsNode>[];
styles.add(new DiagnosticsProperty<Color>('${prefix}color', color, defaultValue: null));
styles.add(new StringProperty('${prefix}family', fontFamily, defaultValue: null, quoted: false));
......
......@@ -795,13 +795,7 @@ void main() {
});
testWidgets('TextField with default helperStyle', (WidgetTester tester) async {
final ThemeData themeData = ThemeData.localize(
new ThemeData(
hintColor: Colors.blue[500],
),
MaterialTextGeometry.forScriptCategory(MaterialTextGeometry.englishLikeCategory),
);
final ThemeData themeData = new ThemeData(hintColor: Colors.blue[500]);
await tester.pumpWidget(
overlay(
child: new Theme(
......@@ -816,7 +810,7 @@ void main() {
);
final Text helperText = tester.widget(find.text('helper text'));
expect(helperText.style.color, themeData.hintColor);
expect(helperText.style.fontSize, themeData.textTheme.caption.fontSize);
expect(helperText.style.fontSize, MaterialTextGeometry.englishLike.caption.fontSize);
});
testWidgets('TextField with specified helperStyle', (WidgetTester tester) async {
......
......@@ -24,7 +24,8 @@ void main() {
for (TargetPlatform platform in TargetPlatform.values) {
final ThemeData theme = new ThemeData(platform: platform);
final Typography typography = new Typography(platform: platform);
expect(theme.textTheme, typography.black, reason: 'Not using default typography for $platform');
expect(theme.textTheme, typography.black.apply(decoration: TextDecoration.none),
reason: 'Not using default typography for $platform');
}
});
......
......@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/src/foundation/diagnostics.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
......@@ -367,6 +369,56 @@ void main() {
expect(actualFontSize, _kMagicFontSize);
});
testWidgets('Default Theme provides all basic TextStyle properties', (WidgetTester tester) async {
ThemeData theme;
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Builder(
builder: (BuildContext context) {
theme = Theme.of(context);
return const Text('A');
},
),
));
List<TextStyle> extractStyles(TextTheme textTheme) {
return <TextStyle>[
textTheme.display4,
textTheme.display3,
textTheme.display2,
textTheme.display1,
textTheme.headline,
textTheme.title,
textTheme.subhead,
textTheme.body2,
textTheme.body1,
textTheme.caption,
textTheme.button,
];
}
for (TextTheme textTheme in <TextTheme>[theme.textTheme, theme.primaryTextTheme, theme.accentTextTheme]) {
for (TextStyle style in extractStyles(textTheme).map((TextStyle style) => new _TextStyleProxy(style))) {
expect(style.inherit, false);
expect(style.color, isNotNull);
expect(style.fontFamily, isNotNull);
expect(style.fontSize, isNotNull);
expect(style.fontWeight, isNotNull);
expect(style.fontStyle, null);
expect(style.letterSpacing, null);
expect(style.wordSpacing, null);
expect(style.textBaseline, isNotNull);
expect(style.height, null);
expect(style.decoration, TextDecoration.none);
expect(style.decorationColor, null);
expect(style.decorationStyle, null);
expect(style.debugLabel, isNotNull);
}
}
expect(theme.textTheme.display4.debugLabel, 'blackMountainView display4 < englishLike display4');
});
}
int testBuildCalled;
......@@ -388,3 +440,73 @@ class _TestState extends State<Test> {
);
}
}
/// This class exists only to make sure that we test all the properties of the
/// [TextStyle] class. If a property is added/removed/renamed, the analyzer will
/// complain that this class has incorrect overrides.
class _TextStyleProxy implements TextStyle {
_TextStyleProxy(this._delegate);
final TextStyle _delegate;
// Do make sure that all the properties correctly forward to the _delegate.
@override Color get color => _delegate.color;
@override String get debugLabel => _delegate.debugLabel;
@override TextDecoration get decoration => _delegate.decoration;
@override Color get decorationColor => _delegate.decorationColor;
@override TextDecorationStyle get decorationStyle => _delegate.decorationStyle;
@override String get fontFamily => _delegate.fontFamily;
@override double get fontSize => _delegate.fontSize;
@override FontStyle get fontStyle => _delegate.fontStyle;
@override FontWeight get fontWeight => _delegate.fontWeight;
@override double get height => _delegate.height;
@override bool get inherit => _delegate.inherit;
@override double get letterSpacing => _delegate.letterSpacing;
@override TextBaseline get textBaseline => _delegate.textBaseline;
@override double get wordSpacing => _delegate.wordSpacing;
@override
DiagnosticsNode toDiagnosticsNode({String name, DiagnosticsTreeStyle style}) {
throw new UnimplementedError();
}
@override
String toStringShort() {
throw new UnimplementedError();
}
@override
TextStyle apply({Color color, TextDecoration decoration, Color decorationColor, TextDecorationStyle decorationStyle, String fontFamily, 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 new UnimplementedError();
}
@override
RenderComparison compareTo(TextStyle other) {
throw new UnimplementedError();
}
@override
TextStyle copyWith({Color color, String fontFamily, double fontSize, FontWeight fontWeight, FontStyle fontStyle, double letterSpacing, double wordSpacing, TextBaseline textBaseline, double height, TextDecoration decoration, Color decorationColor, TextDecorationStyle decorationStyle, String debugLabel}) {
throw new UnimplementedError();
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties, {String prefix: ''}) {
throw new UnimplementedError();
}
@override
ui.ParagraphStyle getParagraphStyle({TextAlign textAlign, TextDirection textDirection, double textScaleFactor: 1.0, String ellipsis, int maxLines}) {
throw new UnimplementedError();
}
@override
ui.TextStyle getTextStyle({double textScaleFactor: 1.0}) {
throw new UnimplementedError();
}
@override
TextStyle merge(TextStyle other) {
throw new UnimplementedError();
}
}
......@@ -142,4 +142,25 @@ void main() {
expect(s7.fontFamily, 'packages/p/test');
expect(s7.getTextStyle().toString(), 'TextStyle(color: unspecified, decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, fontWeight: unspecified, fontStyle: unspecified, textBaseline: unspecified, fontFamily: packages/p/test, fontSize: unspecified, letterSpacing: unspecified, wordSpacing: unspecified, height: unspecified)');
});
test('TextStyle.debugLabel', () {
const TextStyle unknown = const TextStyle();
const TextStyle foo = const TextStyle(debugLabel: 'foo', fontSize: 1.0);
const TextStyle bar = const TextStyle(debugLabel: 'bar', fontSize: 2.0);
const TextStyle baz = const TextStyle(debugLabel: 'baz', fontSize: 3.0);
expect(unknown.debugLabel, null);
expect(unknown.toString(), 'TextStyle(<all styles inherited>)');
expect(unknown.copyWith().debugLabel, null);
expect(unknown.apply().debugLabel, null);
expect(foo.debugLabel, 'foo');
expect(foo.toString(), 'TextStyle(debugLabel: foo, inherit: true, size: 1.0)');
expect(foo.merge(bar).debugLabel, 'bar < foo');
expect(foo.merge(bar).merge(baz).debugLabel, 'baz < bar < foo');
expect(foo.copyWith().debugLabel, 'copy of foo');
expect(foo.apply().debugLabel, 'modified foo');
expect(TextStyle.lerp(foo, bar, 0.5).debugLabel, 'lerp(foo, bar)');
expect(TextStyle.lerp(foo.merge(bar), baz, 0.5).copyWith().debugLabel, 'copy of lerp(bar < foo, baz)');
});
}
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