Unverified Commit 23f7985e authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Improve how AttributedStrings are presented in the widget inspector (#92450)

parent bd935e5d
...@@ -2839,14 +2839,23 @@ class DiagnosticsProperty<T> extends DiagnosticsNode { ...@@ -2839,14 +2839,23 @@ class DiagnosticsProperty<T> extends DiagnosticsNode {
} }
} }
/// If the [value] of the property equals [defaultValue] the priority [level] /// The default value of this property, when it has not been set to a specific
/// of the property is downgraded to [DiagnosticLevel.fine] as the property /// value.
/// value is uninteresting. ///
/// For most [DiagnosticsProperty] classes, if the [value] of the property
/// equals [defaultValue], then the priority [level] of the property is
/// downgraded to [DiagnosticLevel.fine] on the basis that the property value
/// is uninteresting. This is implemented by [isInteresting].
/// ///
/// The [defaultValue] is [kNoDefaultValue] by default. Otherwise it must be of /// The [defaultValue] is [kNoDefaultValue] by default. Otherwise it must be of
/// type `T?`. /// type `T?`.
final Object? defaultValue; final Object? defaultValue;
/// Whether to consider the property's value interesting. When a property is
/// uninteresting, its [level] is downgraded to [DiagnosticLevel.fine]
/// regardless of the value provided as the constructor's `level` argument.
bool get isInteresting => defaultValue == kNoDefaultValue || value != defaultValue;
final DiagnosticLevel _defaultLevel; final DiagnosticLevel _defaultLevel;
/// Priority level of the diagnostic used to control which diagnostics should /// Priority level of the diagnostic used to control which diagnostics should
...@@ -2870,8 +2879,7 @@ class DiagnosticsProperty<T> extends DiagnosticsNode { ...@@ -2870,8 +2879,7 @@ class DiagnosticsProperty<T> extends DiagnosticsNode {
if (value == null && missingIfNull) if (value == null && missingIfNull)
return DiagnosticLevel.warning; return DiagnosticLevel.warning;
// Use a low level when the value matches the default value. if (!isInteresting)
if (defaultValue != kNoDefaultValue && value == defaultValue)
return DiagnosticLevel.fine; return DiagnosticLevel.fine;
return _defaultLevel; return _defaultLevel;
...@@ -3549,7 +3557,9 @@ class DiagnosticsBlock extends DiagnosticsNode { ...@@ -3549,7 +3557,9 @@ class DiagnosticsBlock extends DiagnosticsNode {
@override @override
final DiagnosticLevel level; final DiagnosticLevel level;
final String? _description; final String? _description;
@override @override
final Object? value; final Object? value;
......
...@@ -255,6 +255,57 @@ class AttributedString { ...@@ -255,6 +255,57 @@ class AttributedString {
} }
} }
/// A [DiagnosticsProperty] for [AttributedString]s, which shows a string
/// when there are no attributes, and more details otherwise.
class AttributedStringProperty extends DiagnosticsProperty<AttributedString> {
/// Create a diagnostics property for an [AttributedString] object.
///
/// Such properties are used with [SemanticsData] objects.
AttributedStringProperty(
String name,
AttributedString? value, {
bool showName = true,
this.showWhenEmpty = false,
Object? defaultValue = kNoDefaultValue,
DiagnosticLevel level = DiagnosticLevel.info,
String? description,
}) : assert(showName != null),
assert(level != null),
super(
name,
value,
showName: showName,
defaultValue: defaultValue,
level: level,
description: description,
);
/// Whether to show the property when the [value] is an [AttributedString]
/// whose [AttributedString.string] is the empty string.
///
/// This overrides [defaultValue].
final bool showWhenEmpty;
@override
bool get isInteresting => super.isInteresting && (showWhenEmpty || (value != null && value!.string.isNotEmpty));
@override
String valueToString({TextTreeConfiguration? parentConfiguration}) {
if (value == null)
return 'null';
String text = value!.string;
if (parentConfiguration != null &&
!parentConfiguration.lineBreakProperties) {
// This follows a similar pattern to StringProperty.
text = text.replaceAll('\n', r'\n');
}
if (value!.attributes.isEmpty) {
return '"$text"';
}
return '"$text" ${value!.attributes}'; // the attributes will be in square brackets since they're a list
}
}
/// Summary information about a [SemanticsNode] object. /// Summary information about a [SemanticsNode] object.
/// ///
/// A semantics node might [SemanticsNode.mergeAllDescendantsIntoThisNode], /// A semantics node might [SemanticsNode.mergeAllDescendantsIntoThisNode],
...@@ -303,9 +354,9 @@ class SemanticsData with Diagnosticable { ...@@ -303,9 +354,9 @@ class SemanticsData with Diagnosticable {
assert(attributedHint != null), assert(attributedHint != null),
assert(attributedLabel.string == '' || textDirection != null, 'A SemanticsData object with label "${attributedLabel.string}" had a null textDirection.'), assert(attributedLabel.string == '' || textDirection != null, 'A SemanticsData object with label "${attributedLabel.string}" had a null textDirection.'),
assert(attributedValue.string == '' || textDirection != null, 'A SemanticsData object with value "${attributedValue.string}" had a null textDirection.'), assert(attributedValue.string == '' || textDirection != null, 'A SemanticsData object with value "${attributedValue.string}" had a null textDirection.'),
assert(attributedHint.string == '' || textDirection != null, 'A SemanticsData object with hint "${attributedHint.string}" had a null textDirection.'),
assert(attributedDecreasedValue.string == '' || textDirection != null, 'A SemanticsData object with decreasedValue "${attributedDecreasedValue.string}" had a null textDirection.'), assert(attributedDecreasedValue.string == '' || textDirection != null, 'A SemanticsData object with decreasedValue "${attributedDecreasedValue.string}" had a null textDirection.'),
assert(attributedIncreasedValue.string == '' || textDirection != null, 'A SemanticsData object with increasedValue "${attributedIncreasedValue.string}" had a null textDirection.'), assert(attributedIncreasedValue.string == '' || textDirection != null, 'A SemanticsData object with increasedValue "${attributedIncreasedValue.string}" had a null textDirection.'),
assert(attributedHint.string == '' || textDirection != null, 'A SemanticsData object with hint "${attributedHint.string}" had a null textDirection.'),
assert(rect != null); assert(rect != null);
/// A bit field of [SemanticsFlag]s that apply to this node. /// A bit field of [SemanticsFlag]s that apply to this node.
...@@ -317,62 +368,82 @@ class SemanticsData with Diagnosticable { ...@@ -317,62 +368,82 @@ class SemanticsData with Diagnosticable {
/// A textual description for the current label of the node. /// A textual description for the current label of the node.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// This exposes the raw text of the [attributedLabel].
String get label => attributedLabel.string; String get label => attributedLabel.string;
/// A textual description for the current label of the node in /// A textual description for the current label of the node in
/// [AttributedString] format. /// [AttributedString] format.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// See also [label], which exposes just the raw text.
final AttributedString attributedLabel; final AttributedString attributedLabel;
/// A textual description for the current value of the node. /// A textual description for the current value of the node.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// This exposes the raw text of the [attributedValue].
String get value => attributedValue.string; String get value => attributedValue.string;
/// A textual description for the current value of the node in /// A textual description for the current value of the node in
/// [AttributedString] format. /// [AttributedString] format.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// See also [value], which exposes just the raw text.
final AttributedString attributedValue; final AttributedString attributedValue;
/// The value that [value] will become after performing a /// The value that [value] will become after performing a
/// [SemanticsAction.increase] action. /// [SemanticsAction.increase] action.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// This exposes the raw text of the [attributedIncreasedValue].
String get increasedValue => attributedIncreasedValue.string; String get increasedValue => attributedIncreasedValue.string;
/// The value that [value] will become after performing a /// The value that [value] will become after performing a
/// [SemanticsAction.increase] action in [AttributedString] format. /// [SemanticsAction.increase] action in [AttributedString] format.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// See also [increasedValue], which exposes just the raw text.
final AttributedString attributedIncreasedValue; final AttributedString attributedIncreasedValue;
/// The value that [value] will become after performing a /// The value that [value] will become after performing a
/// [SemanticsAction.decrease] action. /// [SemanticsAction.decrease] action.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// This exposes the raw text of the [attributedDecreasedValue].
String get decreasedValue => attributedDecreasedValue.string; String get decreasedValue => attributedDecreasedValue.string;
/// The value that [value] will become after performing a /// The value that [value] will become after performing a
/// [SemanticsAction.decrease] action in [AttributedString] format. /// [SemanticsAction.decrease] action in [AttributedString] format.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// See also [decreasedValue], which exposes just the raw text.
final AttributedString attributedDecreasedValue; final AttributedString attributedDecreasedValue;
/// A brief description of the result of performing an action on this node. /// A brief description of the result of performing an action on this node.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// This exposes the raw text of the [attributedHint].
String get hint => attributedHint.string; String get hint => attributedHint.string;
/// A brief description of the result of performing an action on this node /// A brief description of the result of performing an action on this node
/// in [AttributedString] format. /// in [AttributedString] format.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// See also [hint], which exposes just the raw text.
final AttributedString attributedHint; final AttributedString attributedHint;
/// The reading direction for the text in [label], [value], [hint], /// The reading direction for the text in [label], [value],
/// [increasedValue], and [decreasedValue]. /// [increasedValue], [decreasedValue], and [hint].
final TextDirection? textDirection; final TextDirection? textDirection;
/// The currently selected text (or the position of the cursor) within [value] /// The currently selected text (or the position of the cursor) within [value]
...@@ -524,11 +595,11 @@ class SemanticsData with Diagnosticable { ...@@ -524,11 +595,11 @@ class SemanticsData with Diagnosticable {
describeEnum(flag), describeEnum(flag),
]; ];
properties.add(IterableProperty<String>('flags', flagSummary, ifEmpty: null)); properties.add(IterableProperty<String>('flags', flagSummary, ifEmpty: null));
properties.add(StringProperty('label', attributedLabel.attributes.isEmpty ? label : attributedLabel.toString(), defaultValue: '')); properties.add(AttributedStringProperty('label', attributedLabel));
properties.add(StringProperty('value', attributedValue.attributes.isEmpty? value :attributedValue.toString(), defaultValue: '')); properties.add(AttributedStringProperty('value', attributedValue));
properties.add(StringProperty('increasedValue', attributedIncreasedValue.attributes.isEmpty? increasedValue :attributedIncreasedValue.toString(), defaultValue: '')); properties.add(AttributedStringProperty('increasedValue', attributedIncreasedValue));
properties.add(StringProperty('decreasedValue', attributedDecreasedValue.attributes.isEmpty? decreasedValue :attributedDecreasedValue.toString(), defaultValue: '')); properties.add(AttributedStringProperty('decreasedValue', attributedDecreasedValue));
properties.add(StringProperty('hint', attributedHint.attributes.isEmpty? hint :attributedHint.toString(), defaultValue: '')); properties.add(AttributedStringProperty('hint', attributedHint));
properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null)); properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
if (textSelection?.isValid == true) if (textSelection?.isValid == true)
properties.add(MessageProperty('textSelection', '[${textSelection!.start}, ${textSelection!.end}]')); properties.add(MessageProperty('textSelection', '[${textSelection!.start}, ${textSelection!.end}]'));
...@@ -977,10 +1048,10 @@ class SemanticsProperties extends DiagnosticableTree { ...@@ -977,10 +1048,10 @@ class SemanticsProperties extends DiagnosticableTree {
/// ///
/// * [SemanticsConfiguration.label] for a description of how this is exposed /// * [SemanticsConfiguration.label] for a description of how this is exposed
/// in TalkBack and VoiceOver. /// in TalkBack and VoiceOver.
/// * [attributedLabel] for a [AttributedString] version of this property. /// * [attributedLabel] for an [AttributedString] version of this property.
final String? label; final String? label;
/// Provides a [AttributedString] version of textual description of the widget. /// Provides an [AttributedString] version of textual description of the widget.
/// ///
/// If a [attributedLabel] is provided, there must either by an ambient /// If a [attributedLabel] is provided, there must either by an ambient
/// [Directionality] or an explicit [textDirection] should be provided. /// [Directionality] or an explicit [textDirection] should be provided.
...@@ -1007,10 +1078,10 @@ class SemanticsProperties extends DiagnosticableTree { ...@@ -1007,10 +1078,10 @@ class SemanticsProperties extends DiagnosticableTree {
/// ///
/// * [SemanticsConfiguration.value] for a description of how this is exposed /// * [SemanticsConfiguration.value] for a description of how this is exposed
/// in TalkBack and VoiceOver. /// in TalkBack and VoiceOver.
/// * [attributedLabel] for a [AttributedString] version of this property. /// * [attributedLabel] for an [AttributedString] version of this property.
final String? value; final String? value;
/// Provides a [AttributedString] version of textual description of the value /// Provides an [AttributedString] version of textual description of the value
/// of the widget. /// of the widget.
/// ///
/// If a [attributedValue] is provided, there must either by an ambient /// If a [attributedValue] is provided, there must either by an ambient
...@@ -1040,7 +1111,7 @@ class SemanticsProperties extends DiagnosticableTree { ...@@ -1040,7 +1111,7 @@ class SemanticsProperties extends DiagnosticableTree {
/// ///
/// * [SemanticsConfiguration.increasedValue] for a description of how this /// * [SemanticsConfiguration.increasedValue] for a description of how this
/// is exposed in TalkBack and VoiceOver. /// is exposed in TalkBack and VoiceOver.
/// * [attributedIncreasedValue] for a [AttributedString] version of this /// * [attributedIncreasedValue] for an [AttributedString] version of this
/// property. /// property.
final String? increasedValue; final String? increasedValue;
...@@ -1075,7 +1146,7 @@ class SemanticsProperties extends DiagnosticableTree { ...@@ -1075,7 +1146,7 @@ class SemanticsProperties extends DiagnosticableTree {
/// ///
/// * [SemanticsConfiguration.decreasedValue] for a description of how this /// * [SemanticsConfiguration.decreasedValue] for a description of how this
/// is exposed in TalkBack and VoiceOver. /// is exposed in TalkBack and VoiceOver.
/// * [attributedDecreasedValue] for a [AttributedString] version of this /// * [attributedDecreasedValue] for an [AttributedString] version of this
/// property. /// property.
final String? decreasedValue; final String? decreasedValue;
...@@ -1109,10 +1180,10 @@ class SemanticsProperties extends DiagnosticableTree { ...@@ -1109,10 +1180,10 @@ class SemanticsProperties extends DiagnosticableTree {
/// ///
/// * [SemanticsConfiguration.hint] for a description of how this is exposed /// * [SemanticsConfiguration.hint] for a description of how this is exposed
/// in TalkBack and VoiceOver. /// in TalkBack and VoiceOver.
/// * [attributedHint] for a [AttributedString] version of this property. /// * [attributedHint] for an [AttributedString] version of this property.
final String? hint; final String? hint;
/// Provides a [AttributedString] version of brief textual description of the /// Provides an [AttributedString] version of brief textual description of the
/// result of an action performed on the widget. /// result of an action performed on the widget.
/// ///
/// If a [attributedHint] is provided, there must either by an ambient /// If a [attributedHint] is provided, there must either by an ambient
...@@ -1138,8 +1209,8 @@ class SemanticsProperties extends DiagnosticableTree { ...@@ -1138,8 +1209,8 @@ class SemanticsProperties extends DiagnosticableTree {
/// On iOS, these are always ignored and the default [hint] is used instead. /// On iOS, these are always ignored and the default [hint] is used instead.
final SemanticsHintOverrides? hintOverrides; final SemanticsHintOverrides? hintOverrides;
/// The reading direction of the [label], [value], [hint], [increasedValue], /// The reading direction of the [label], [value], [increasedValue],
/// and [decreasedValue]. /// [decreasedValue], and [hint].
/// ///
/// Defaults to the ambient [Directionality]. /// Defaults to the ambient [Directionality].
final TextDirection? textDirection; final TextDirection? textDirection;
...@@ -1409,15 +1480,19 @@ class SemanticsProperties extends DiagnosticableTree { ...@@ -1409,15 +1480,19 @@ class SemanticsProperties extends DiagnosticableTree {
super.debugFillProperties(properties); super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<bool>('checked', checked, defaultValue: null)); properties.add(DiagnosticsProperty<bool>('checked', checked, defaultValue: null));
properties.add(DiagnosticsProperty<bool>('selected', selected, defaultValue: null)); properties.add(DiagnosticsProperty<bool>('selected', selected, defaultValue: null));
properties.add(StringProperty('label', label, defaultValue: '')); properties.add(StringProperty('label', label, defaultValue: null));
properties.add(StringProperty('attributedLabel', attributedLabel.toString(), defaultValue: '')); properties.add(AttributedStringProperty('attributedLabel', attributedLabel, defaultValue: null));
properties.add(StringProperty('value', value)); properties.add(StringProperty('value', value, defaultValue: null));
properties.add(StringProperty('attributedValue', attributedValue.toString(), defaultValue: '')); properties.add(AttributedStringProperty('attributedValue', attributedValue, defaultValue: null));
properties.add(StringProperty('hint', hint)); properties.add(StringProperty('increasedValue', value, defaultValue: null));
properties.add(StringProperty('attributedHint', attributedHint.toString(), defaultValue: '')); properties.add(AttributedStringProperty('attributedIncreasedValue', attributedIncreasedValue, defaultValue: null));
properties.add(StringProperty('decreasedValue', value, defaultValue: null));
properties.add(AttributedStringProperty('attributedDecreasedValue', attributedDecreasedValue, defaultValue: null));
properties.add(StringProperty('hint', hint, defaultValue: null));
properties.add(AttributedStringProperty('attributedHint', attributedHint, defaultValue: null));
properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null)); properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
properties.add(DiagnosticsProperty<SemanticsSortKey>('sortKey', sortKey, defaultValue: null)); properties.add(DiagnosticsProperty<SemanticsSortKey>('sortKey', sortKey, defaultValue: null));
properties.add(DiagnosticsProperty<SemanticsHintOverrides>('hintOverrides', hintOverrides)); properties.add(DiagnosticsProperty<SemanticsHintOverrides>('hintOverrides', hintOverrides, defaultValue: null));
} }
@override @override
...@@ -1837,26 +1912,26 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { ...@@ -1837,26 +1912,26 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
} }
bool _isDifferentFromCurrentSemanticAnnotation(SemanticsConfiguration config) { bool _isDifferentFromCurrentSemanticAnnotation(SemanticsConfiguration config) {
return _attributedLabel != config.attributedLabel || return _attributedLabel != config.attributedLabel
_attributedHint != config.attributedHint || || _attributedHint != config.attributedHint
_elevation != config.elevation || || _elevation != config.elevation
_thickness != config.thickness || || _thickness != config.thickness
_attributedValue != config.attributedValue || || _attributedValue != config.attributedValue
_attributedIncreasedValue != config.attributedIncreasedValue || || _attributedIncreasedValue != config.attributedIncreasedValue
_attributedDecreasedValue != config.attributedDecreasedValue || || _attributedDecreasedValue != config.attributedDecreasedValue
_flags != config._flags || || _flags != config._flags
_textDirection != config.textDirection || || _textDirection != config.textDirection
_sortKey != config._sortKey || || _sortKey != config._sortKey
_textSelection != config._textSelection || || _textSelection != config._textSelection
_scrollPosition != config._scrollPosition || || _scrollPosition != config._scrollPosition
_scrollExtentMax != config._scrollExtentMax || || _scrollExtentMax != config._scrollExtentMax
_scrollExtentMin != config._scrollExtentMin || || _scrollExtentMin != config._scrollExtentMin
_actionsAsBits != config._actionsAsBits || || _actionsAsBits != config._actionsAsBits
indexInParent != config.indexInParent || || indexInParent != config.indexInParent
platformViewId != config.platformViewId || || platformViewId != config.platformViewId
_maxValueLength != config._maxValueLength || || _maxValueLength != config._maxValueLength
_currentValueLength != config._currentValueLength || || _currentValueLength != config._currentValueLength
_mergeAllDescendantsIntoThisNode != config.isMergingSemanticsOfDescendants; || _mergeAllDescendantsIntoThisNode != config.isMergingSemanticsOfDescendants;
} }
// TAGS, LABELS, ACTIONS // TAGS, LABELS, ACTIONS
...@@ -1883,74 +1958,93 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { ...@@ -1883,74 +1958,93 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
/// A textual description of this node. /// A textual description of this node.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// This exposes the raw text of the [attributedLabel].
String get label => _attributedLabel.string; String get label => _attributedLabel.string;
/// A textual description of this node in [AttributedString] format. /// A textual description of this node in [AttributedString] format.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// See also [label], which exposes just the raw text.
AttributedString get attributedLabel => _attributedLabel; AttributedString get attributedLabel => _attributedLabel;
AttributedString _attributedLabel = _kEmptyConfig.attributedLabel; AttributedString _attributedLabel = _kEmptyConfig.attributedLabel;
/// A textual description for the current value of the node. /// A textual description for the current value of the node.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// This exposes the raw text of the [attributedValue].
String get value => _attributedValue.string; String get value => _attributedValue.string;
/// A textual description for the current value of the node in /// A textual description for the current value of the node in
/// [AttributedString] format. /// [AttributedString] format.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// See also [value], which exposes just the raw text.
AttributedString get attributedValue => _attributedValue; AttributedString get attributedValue => _attributedValue;
AttributedString _attributedValue = _kEmptyConfig.attributedValue; AttributedString _attributedValue = _kEmptyConfig.attributedValue;
/// The value that [value] will have after a [SemanticsAction.decrease] action /// The value that [value] will have after a [SemanticsAction.increase] action
/// has been performed. /// has been performed.
/// ///
/// This property is only valid if the [SemanticsAction.decrease] action is /// This property is only valid if the [SemanticsAction.increase] action is
/// available on this node. /// available on this node.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
String get decreasedValue => _attributedDecreasedValue.string; ///
/// This exposes the raw text of the [attributedIncreasedValue].
String get increasedValue => _attributedIncreasedValue.string;
/// The value in [AttributedString] format that [value] or [attributedValue] /// The value in [AttributedString] format that [value] or [attributedValue]
/// will have after a [SemanticsAction.decrease] action has been performed. /// will have after a [SemanticsAction.increase] action has been performed.
/// ///
/// This property is only valid if the [SemanticsAction.decrease] action is /// This property is only valid if the [SemanticsAction.increase] action is
/// available on this node. /// available on this node.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
AttributedString get attributedDecreasedValue => _attributedDecreasedValue; ///
AttributedString _attributedDecreasedValue = _kEmptyConfig.attributedDecreasedValue; /// See also [increasedValue], which exposes just the raw text.
AttributedString get attributedIncreasedValue => _attributedIncreasedValue;
AttributedString _attributedIncreasedValue = _kEmptyConfig.attributedIncreasedValue;
/// The value that [value] will have after a [SemanticsAction.increase] action /// The value that [value] will have after a [SemanticsAction.decrease] action
/// has been performed. /// has been performed.
/// ///
/// This property is only valid if the [SemanticsAction.increase] action is /// This property is only valid if the [SemanticsAction.decrease] action is
/// available on this node. /// available on this node.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
String get increasedValue => _attributedIncreasedValue.string; ///
/// This exposes the raw text of the [attributedDecreasedValue].
String get decreasedValue => _attributedDecreasedValue.string;
/// The value in [AttributedString] format that [value] or [attributedValue] /// The value in [AttributedString] format that [value] or [attributedValue]
/// will have after a [SemanticsAction.increase] action has been performed. /// will have after a [SemanticsAction.decrease] action has been performed.
/// ///
/// This property is only valid if the [SemanticsAction.increase] action is /// This property is only valid if the [SemanticsAction.decrease] action is
/// available on this node. /// available on this node.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
AttributedString get attributedIncreasedValue => _attributedIncreasedValue; ///
AttributedString _attributedIncreasedValue = _kEmptyConfig.attributedIncreasedValue; /// See also [decreasedValue], which exposes just the raw text.
AttributedString get attributedDecreasedValue => _attributedDecreasedValue;
AttributedString _attributedDecreasedValue = _kEmptyConfig.attributedDecreasedValue;
/// A brief description of the result of performing an action on this node. /// A brief description of the result of performing an action on this node.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// This exposes the raw text of the [attributedHint].
String get hint => _attributedHint.string; String get hint => _attributedHint.string;
/// A brief description of the result of performing an action on this node /// A brief description of the result of performing an action on this node
/// in [AttributedString] format. /// in [AttributedString] format.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// See also [hint], which exposes just the raw text.
AttributedString get attributedHint => _attributedHint; AttributedString get attributedHint => _attributedHint;
AttributedString _attributedHint = _kEmptyConfig.attributedHint; AttributedString _attributedHint = _kEmptyConfig.attributedHint;
...@@ -2517,11 +2611,11 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { ...@@ -2517,11 +2611,11 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
properties.add(IterableProperty<String>('flags', flags, ifEmpty: null)); properties.add(IterableProperty<String>('flags', flags, ifEmpty: null));
properties.add(FlagProperty('isInvisible', value: isInvisible, ifTrue: 'invisible')); properties.add(FlagProperty('isInvisible', value: isInvisible, ifTrue: 'invisible'));
properties.add(FlagProperty('isHidden', value: hasFlag(SemanticsFlag.isHidden), ifTrue: 'HIDDEN')); properties.add(FlagProperty('isHidden', value: hasFlag(SemanticsFlag.isHidden), ifTrue: 'HIDDEN'));
properties.add(StringProperty('label', _attributedLabel.attributes.isEmpty ? _attributedLabel.string : _attributedLabel.toString(), defaultValue: '')); properties.add(AttributedStringProperty('label', _attributedLabel));
properties.add(StringProperty('value', _attributedValue.attributes.isEmpty ? _attributedValue.string : _attributedValue.toString(), defaultValue: '')); properties.add(AttributedStringProperty('value', _attributedValue));
properties.add(StringProperty('increasedValue', _attributedIncreasedValue.attributes.isEmpty ? _attributedIncreasedValue.string : _attributedIncreasedValue.toString(), defaultValue: '')); properties.add(AttributedStringProperty('increasedValue', _attributedIncreasedValue));
properties.add(StringProperty('decreasedValue', _attributedDecreasedValue.attributes.isEmpty ? _attributedDecreasedValue.string : _attributedDecreasedValue.toString(), defaultValue: '')); properties.add(AttributedStringProperty('decreasedValue', _attributedDecreasedValue));
properties.add(StringProperty('hint', _attributedHint.attributes.isEmpty ? _attributedHint.string : _attributedHint.toString(), defaultValue: '')); properties.add(AttributedStringProperty('hint', _attributedHint));
properties.add(EnumProperty<TextDirection>('textDirection', _textDirection, defaultValue: null)); properties.add(EnumProperty<TextDirection>('textDirection', _textDirection, defaultValue: null));
properties.add(DiagnosticsProperty<SemanticsSortKey>('sortKey', sortKey, defaultValue: null)); properties.add(DiagnosticsProperty<SemanticsSortKey>('sortKey', sortKey, defaultValue: null));
if (_textSelection?.isValid == true) if (_textSelection?.isValid == true)
...@@ -3692,7 +3786,8 @@ class SemanticsConfiguration { ...@@ -3692,7 +3786,8 @@ class SemanticsConfiguration {
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
/// ///
/// See also: /// See also:
/// * [attributedLabel]: which is the [AttributedString] of this property. ///
/// * [attributedLabel], which is the [AttributedString] of this property.
String get label => _attributedLabel.string; String get label => _attributedLabel.string;
set label(String label) { set label(String label) {
assert(label != null); assert(label != null);
...@@ -3710,6 +3805,10 @@ class SemanticsConfiguration { ...@@ -3710,6 +3805,10 @@ class SemanticsConfiguration {
/// concatenated value is then used as the `Text` description. /// concatenated value is then used as the `Text` description.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// See also:
///
/// * [label], which is the raw text of this property.
AttributedString get attributedLabel => _attributedLabel; AttributedString get attributedLabel => _attributedLabel;
AttributedString _attributedLabel = AttributedString(''); AttributedString _attributedLabel = AttributedString('');
set attributedLabel(AttributedString attributedLabel) { set attributedLabel(AttributedString attributedLabel) {
...@@ -3726,10 +3825,10 @@ class SemanticsConfiguration { ...@@ -3726,10 +3825,10 @@ class SemanticsConfiguration {
/// See also: /// See also:
/// ///
/// * [attributedValue], which is the [AttributedString] of this property. /// * [attributedValue], which is the [AttributedString] of this property.
/// * [decreasedValue] and [attributedDecreasedValue], describes what /// * [increasedValue] and [attributedIncreasedValue], which describe what
/// [value] will be after performing [SemanticsAction.decrease].
/// * [increasedValue] and [attributedIncreasedValue], describes what
/// [value] will be after performing [SemanticsAction.increase]. /// [value] will be after performing [SemanticsAction.increase].
/// * [decreasedValue] and [attributedDecreasedValue], which describe what
/// [value] will be after performing [SemanticsAction.decrease].
String get value => _attributedValue.string; String get value => _attributedValue.string;
set value(String value) { set value(String value) {
assert(value != null); assert(value != null);
...@@ -3750,10 +3849,11 @@ class SemanticsConfiguration { ...@@ -3750,10 +3849,11 @@ class SemanticsConfiguration {
/// ///
/// See also: /// See also:
/// ///
/// * [attributedDecreasedValue], describes what [value] will be after /// * [value], which is the raw text of this property.
/// performing [SemanticsAction.decrease]. /// * [attributedIncreasedValue], which describes what [value] will be after
/// * [attributedIncreasedValue], describes what [value] will be after
/// performing [SemanticsAction.increase]. /// performing [SemanticsAction.increase].
/// * [attributedDecreasedValue], which describes what [value] will be after
/// performing [SemanticsAction.decrease].
AttributedString get attributedValue => _attributedValue; AttributedString get attributedValue => _attributedValue;
AttributedString _attributedValue = AttributedString(''); AttributedString _attributedValue = AttributedString('');
set attributedValue(AttributedString attributedValue) { set attributedValue(AttributedString attributedValue) {
...@@ -3762,70 +3862,83 @@ class SemanticsConfiguration { ...@@ -3762,70 +3862,83 @@ class SemanticsConfiguration {
} }
/// The value that [value] will have after performing a /// The value that [value] will have after performing a
/// [SemanticsAction.decrease] action. /// [SemanticsAction.increase] action.
/// ///
/// Setting this attribute will override the [attributedDecreasedValue]. /// Setting this attribute will override the [attributedIncreasedValue].
/// ///
/// One of the [attributedDecreasedValue] or [decreasedValue] must be set if /// One of the [attributedIncreasedValue] or [increasedValue] must be set if
/// a handler for [SemanticsAction.decrease] is provided and one of the /// a handler for [SemanticsAction.increase] is provided and one of the
/// [value] or [attributedValue] is set. /// [value] or [attributedValue] is set.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
String get decreasedValue => _attributedDecreasedValue.string; ///
set decreasedValue(String decreasedValue) { /// See also:
assert(decreasedValue != null); ///
_attributedDecreasedValue = AttributedString(decreasedValue); /// * [attributedIncreasedValue], which is the [AttributedString] of this property.
String get increasedValue => _attributedIncreasedValue.string;
set increasedValue(String increasedValue) {
assert(increasedValue != null);
_attributedIncreasedValue = AttributedString(increasedValue);
_hasBeenAnnotated = true; _hasBeenAnnotated = true;
} }
/// The value that [value] will have after performing a /// The value that [value] will have after performing a
/// [SemanticsAction.decrease] action in [AttributedString] format. /// [SemanticsAction.increase] action in [AttributedString] format.
/// ///
/// One of the [attributedDecreasedValue] or [decreasedValue] must be set if /// One of the [attributedIncreasedValue] or [increasedValue] must be set if
/// a handler for [SemanticsAction.decrease] is provided and one of the /// a handler for [SemanticsAction.increase] is provided and one of the
/// [value] or [attributedValue] is set. /// [value] or [attributedValue] is set.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
AttributedString get attributedDecreasedValue => _attributedDecreasedValue; ///
AttributedString _attributedDecreasedValue = AttributedString(''); /// See also:
set attributedDecreasedValue(AttributedString attributedDecreasedValue) { ///
_attributedDecreasedValue = attributedDecreasedValue; /// * [increasedValue], which is the raw text of this property.
AttributedString get attributedIncreasedValue => _attributedIncreasedValue;
AttributedString _attributedIncreasedValue = AttributedString('');
set attributedIncreasedValue(AttributedString attributedIncreasedValue) {
_attributedIncreasedValue = attributedIncreasedValue;
_hasBeenAnnotated = true; _hasBeenAnnotated = true;
} }
/// The value that [value] will have after performing a /// The value that [value] will have after performing a
/// [SemanticsAction.increase] action. /// [SemanticsAction.decrease] action.
/// ///
/// Setting this attribute will override the [attributedIncreasedValue]. /// Setting this attribute will override the [attributedDecreasedValue].
/// ///
/// One of the [attributedIncreasedValue] or [increasedValue] must be set if /// One of the [attributedDecreasedValue] or [decreasedValue] must be set if
/// a handler for [SemanticsAction.increase] is provided and one of the /// a handler for [SemanticsAction.decrease] is provided and one of the
/// [value] or [attributedValue] is set. /// [value] or [attributedValue] is set.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
String get increasedValue => _attributedIncreasedValue.string; ///
set increasedValue(String increasedValue) { /// * [attributedDecreasedValue], which is the [AttributedString] of this property.
assert(increasedValue != null); String get decreasedValue => _attributedDecreasedValue.string;
_attributedIncreasedValue = AttributedString(increasedValue); set decreasedValue(String decreasedValue) {
assert(decreasedValue != null);
_attributedDecreasedValue = AttributedString(decreasedValue);
_hasBeenAnnotated = true; _hasBeenAnnotated = true;
} }
/// The value that [value] will have after performing a /// The value that [value] will have after performing a
/// [SemanticsAction.increase] action in [AttributedString] format. /// [SemanticsAction.decrease] action in [AttributedString] format.
/// ///
/// One of the [attributedIncreasedValue] or [increasedValue] must be set if /// One of the [attributedDecreasedValue] or [decreasedValue] must be set if
/// a handler for [SemanticsAction.increase] is provided and one of the /// a handler for [SemanticsAction.decrease] is provided and one of the
/// [value] or [attributedValue] is set. /// [value] or [attributedValue] is set.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
AttributedString get attributedIncreasedValue => _attributedIncreasedValue; ///
AttributedString _attributedIncreasedValue = AttributedString(''); /// See also:
set attributedIncreasedValue(AttributedString attributedIncreasedValue) { ///
_attributedIncreasedValue = attributedIncreasedValue; /// * [decreasedValue], which is the raw text of this property.
AttributedString get attributedDecreasedValue => _attributedDecreasedValue;
AttributedString _attributedDecreasedValue = AttributedString('');
set attributedDecreasedValue(AttributedString attributedDecreasedValue) {
_attributedDecreasedValue = attributedDecreasedValue;
_hasBeenAnnotated = true; _hasBeenAnnotated = true;
} }
/// A brief description of the result of performing an action on this node. /// A brief description of the result of performing an action on this node.
/// ///
/// Setting this attribute will override the [attributedHint]. /// Setting this attribute will override the [attributedHint].
...@@ -3833,7 +3946,8 @@ class SemanticsConfiguration { ...@@ -3833,7 +3946,8 @@ class SemanticsConfiguration {
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
/// ///
/// See also: /// See also:
/// * [attributedHint]: which is the [AttributedString] of this property. ///
/// * [attributedHint], which is the [AttributedString] of this property.
String get hint => _attributedHint.string; String get hint => _attributedHint.string;
set hint(String hint) { set hint(String hint) {
assert(hint != null); assert(hint != null);
...@@ -3851,6 +3965,10 @@ class SemanticsConfiguration { ...@@ -3851,6 +3965,10 @@ class SemanticsConfiguration {
/// concatenated value is then used as the `Text` description. /// concatenated value is then used as the `Text` description.
/// ///
/// The reading direction is given by [textDirection]. /// The reading direction is given by [textDirection].
///
/// See also:
///
/// * [hint], which is the raw text of this property.
AttributedString get attributedHint => _attributedHint; AttributedString get attributedHint => _attributedHint;
AttributedString _attributedHint = AttributedString(''); AttributedString _attributedHint = AttributedString('');
set attributedHint(AttributedString attributedHint) { set attributedHint(AttributedString attributedHint) {
......
...@@ -69,6 +69,10 @@ void main() { ...@@ -69,6 +69,10 @@ void main() {
expect(config.label, 'label1'); expect(config.label, 'label1');
expect(config.attributedLabel.string, 'label1'); expect(config.attributedLabel.string, 'label1');
expect(config.attributedLabel.attributes.isEmpty, isTrue); expect(config.attributedLabel.attributes.isEmpty, isTrue);
expect(
(SemanticsNode()..updateWith(config: config)).toString(),
'SemanticsNode#1(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0), invisible, label: "label1")',
);
config.attributedLabel = AttributedString( config.attributedLabel = AttributedString(
'label2', 'label2',
...@@ -81,16 +85,28 @@ void main() { ...@@ -81,16 +85,28 @@ void main() {
expect(config.attributedLabel.attributes.length, 1); expect(config.attributedLabel.attributes.length, 1);
expect(config.attributedLabel.attributes[0] is SpellOutStringAttribute, isTrue); expect(config.attributedLabel.attributes[0] is SpellOutStringAttribute, isTrue);
expect(config.attributedLabel.attributes[0].range, const TextRange(start: 0, end: 1)); expect(config.attributedLabel.attributes[0].range, const TextRange(start: 0, end: 1));
expect(
(SemanticsNode()..updateWith(config: config)).toString(),
'SemanticsNode#2(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0), invisible, label: "label2" [SpellOutStringAttribute(TextRange(start: 0, end: 1))])',
);
config.label = 'label3'; config.label = 'label3';
expect(config.label, 'label3'); expect(config.label, 'label3');
expect(config.attributedLabel.string, 'label3'); expect(config.attributedLabel.string, 'label3');
expect(config.attributedLabel.attributes.isEmpty, isTrue); expect(config.attributedLabel.attributes.isEmpty, isTrue);
expect(
(SemanticsNode()..updateWith(config: config)).toString(),
'SemanticsNode#3(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0), invisible, label: "label3")',
);
config.value = 'value1'; config.value = 'value1';
expect(config.value, 'value1'); expect(config.value, 'value1');
expect(config.attributedValue.string, 'value1'); expect(config.attributedValue.string, 'value1');
expect(config.attributedValue.attributes.isEmpty, isTrue); expect(config.attributedValue.attributes.isEmpty, isTrue);
expect(
(SemanticsNode()..updateWith(config: config)).toString(),
'SemanticsNode#4(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0), invisible, label: "label3", value: "value1")',
);
config.attributedValue = AttributedString( config.attributedValue = AttributedString(
'value2', 'value2',
...@@ -103,16 +119,28 @@ void main() { ...@@ -103,16 +119,28 @@ void main() {
expect(config.attributedValue.attributes.length, 1); expect(config.attributedValue.attributes.length, 1);
expect(config.attributedValue.attributes[0] is SpellOutStringAttribute, isTrue); expect(config.attributedValue.attributes[0] is SpellOutStringAttribute, isTrue);
expect(config.attributedValue.attributes[0].range, const TextRange(start: 0, end: 1)); expect(config.attributedValue.attributes[0].range, const TextRange(start: 0, end: 1));
expect(
(SemanticsNode()..updateWith(config: config)).toString(),
'SemanticsNode#5(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0), invisible, label: "label3", value: "value2" [SpellOutStringAttribute(TextRange(start: 0, end: 1))])',
);
config.value = 'value3'; config.value = 'value3';
expect(config.value, 'value3'); expect(config.value, 'value3');
expect(config.attributedValue.string, 'value3'); expect(config.attributedValue.string, 'value3');
expect(config.attributedValue.attributes.isEmpty, isTrue); expect(config.attributedValue.attributes.isEmpty, isTrue);
expect(
(SemanticsNode()..updateWith(config: config)).toString(),
'SemanticsNode#6(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0), invisible, label: "label3", value: "value3")',
);
config.hint = 'hint1'; config.hint = 'hint1';
expect(config.hint, 'hint1'); expect(config.hint, 'hint1');
expect(config.attributedHint.string, 'hint1'); expect(config.attributedHint.string, 'hint1');
expect(config.attributedHint.attributes.isEmpty, isTrue); expect(config.attributedHint.attributes.isEmpty, isTrue);
expect(
(SemanticsNode()..updateWith(config: config)).toString(),
'SemanticsNode#7(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0), invisible, label: "label3", value: "value3", hint: "hint1")',
);
config.attributedHint = AttributedString( config.attributedHint = AttributedString(
'hint2', 'hint2',
...@@ -125,11 +153,19 @@ void main() { ...@@ -125,11 +153,19 @@ void main() {
expect(config.attributedHint.attributes.length, 1); expect(config.attributedHint.attributes.length, 1);
expect(config.attributedHint.attributes[0] is SpellOutStringAttribute, isTrue); expect(config.attributedHint.attributes[0] is SpellOutStringAttribute, isTrue);
expect(config.attributedHint.attributes[0].range, const TextRange(start: 0, end: 1)); expect(config.attributedHint.attributes[0].range, const TextRange(start: 0, end: 1));
expect(
(SemanticsNode()..updateWith(config: config)).toString(),
'SemanticsNode#8(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0), invisible, label: "label3", value: "value3", hint: "hint2" [SpellOutStringAttribute(TextRange(start: 0, end: 1))])',
);
config.hint = 'hint3'; config.hint = 'hint3';
expect(config.hint, 'hint3'); expect(config.hint, 'hint3');
expect(config.attributedHint.string, 'hint3'); expect(config.attributedHint.string, 'hint3');
expect(config.attributedHint.attributes.isEmpty, isTrue); expect(config.attributedHint.attributes.isEmpty, isTrue);
expect(
(SemanticsNode()..updateWith(config: config)).toString(),
'SemanticsNode#9(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0), invisible, label: "label3", value: "value3", hint: "hint3")',
);
}); });
test('mutate existing semantic node list errors', () { test('mutate existing semantic node list errors', () {
...@@ -654,6 +690,7 @@ void main() { ...@@ -654,6 +690,7 @@ void main() {
expect(result.attributes.length, 2); expect(result.attributes.length, 2);
expect(result.attributes[0].range, const TextRange(start:0, end:4)); expect(result.attributes[0].range, const TextRange(start:0, end:4));
expect(result.attributes[0] is SpellOutStringAttribute, isTrue); expect(result.attributes[0] is SpellOutStringAttribute, isTrue);
expect(result.toString(), "AttributedString('string1string2', attributes: [SpellOutStringAttribute(TextRange(start: 0, end: 4)), LocaleStringAttribute(TextRange(start: 7, end: 11), es-MX)])");
}); });
test('Semantics id does not repeat', () { test('Semantics id does not repeat', () {
......
...@@ -151,6 +151,17 @@ void main() { ...@@ -151,6 +151,17 @@ void main() {
expect(SemanticsUpdateBuilderSpy.observations[1]!.hintAttributes![0] is SpellOutStringAttribute, isTrue); expect(SemanticsUpdateBuilderSpy.observations[1]!.hintAttributes![0] is SpellOutStringAttribute, isTrue);
expect(SemanticsUpdateBuilderSpy.observations[1]!.hintAttributes![0].range, const TextRange(start: 1, end: 2)); expect(SemanticsUpdateBuilderSpy.observations[1]!.hintAttributes![0].range, const TextRange(start: 1, end: 2));
expect(
tester.widget(find.byType(Semantics)).toString(),
'Semantics('
'container: false, '
'properties: SemanticsProperties, '
'attributedLabel: "label" [SpellOutStringAttribute(TextRange(start: 0, end: 5))], '
'attributedValue: "value" [LocaleStringAttribute(TextRange(start: 0, end: 5), en-MX)], '
'attributedHint: "hint" [SpellOutStringAttribute(TextRange(start: 1, end: 2))]' // ignore: missing_whitespace_between_adjacent_strings
')',
);
SemanticsUpdateBuilderSpy.observations.clear(); SemanticsUpdateBuilderSpy.observations.clear();
handle.dispose(); handle.dispose();
}); });
......
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