// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:math' as math;
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'dart:ui' show Offset, Rect, SemanticsAction, SemanticsFlag,
       TextDirection;

import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart' show MatrixUtils, TransformProperty;
import 'package:flutter/services.dart';
import 'package:vector_math/vector_math_64.dart';

import 'binding.dart' show SemanticsBinding;
import 'semantics_event.dart';

export 'dart:ui' show SemanticsAction;
export 'semantics_event.dart';

/// Signature for a function that is called for each [SemanticsNode].
///
/// Return false to stop visiting nodes.
///
/// Used by [SemanticsNode.visitChildren].
typedef SemanticsNodeVisitor = bool Function(SemanticsNode node);

/// Signature for [SemanticsAction]s that move the cursor.
///
/// If `extendSelection` is set to true the cursor movement should extend the
/// current selection or (if nothing is currently selected) start a selection.
typedef MoveCursorHandler = void Function(bool extendSelection);

/// Signature for the [SemanticsAction.setSelection] handlers to change the
/// text selection (or re-position the cursor) to `selection`.
typedef SetSelectionHandler = void Function(TextSelection selection);

typedef _SemanticsActionHandler = void Function(dynamic args);

/// A tag for a [SemanticsNode].
///
/// Tags can be interpreted by the parent of a [SemanticsNode]
/// and depending on the presence of a tag the parent can for example decide
/// how to add the tagged node as a child. Tags are not sent to the engine.
///
/// As an example, the [RenderSemanticsGestureHandler] uses tags to determine
/// if a child node should be excluded from the scrollable area for semantic
/// purposes.
///
/// The provided [name] is only used for debugging. Two tags created with the
/// same [name] and the `new` operator are not considered identical. However,
/// two tags created with the same [name] and the `const` operator are always
/// identical.
class SemanticsTag {
  /// Creates a [SemanticsTag].
  ///
  /// The provided [name] is only used for debugging. Two tags created with the
  /// same [name] and the `new` operator are not considered identical. However,
  /// two tags created with the same [name] and the `const` operator are always
  /// identical.
  const SemanticsTag(this.name);

  /// A human-readable name for this tag used for debugging.
  ///
  /// This string is not used to determine if two tags are identical.
  final String name;

  @override
  String toString() => '${objectRuntimeType(this, 'SemanticsTag')}($name)';
}

/// An identifier of a custom semantics action.
///
/// Custom semantics actions can be provided to make complex user
/// interactions more accessible. For instance, if an application has a
/// drag-and-drop list that requires the user to press and hold an item
/// to move it, users interacting with the application using a hardware
/// switch may have difficulty. This can be made accessible by creating custom
/// actions and pairing them with handlers that move a list item up or down in
/// the list.
///
/// In Android, these actions are presented in the local context menu. In iOS,
/// these are presented in the radial context menu.
///
/// Localization and text direction do not automatically apply to the provided
/// label or hint.
///
/// Instances of this class should either be instantiated with const or
/// new instances cached in static fields.
///
/// See also:
///
///  * [SemanticsProperties], where the handler for a custom action is provided.
@immutable
class CustomSemanticsAction {
  /// Creates a new [CustomSemanticsAction].
  ///
  /// The [label] must not be null or the empty string.
  const CustomSemanticsAction({@required this.label})
    : assert(label != null),
      assert(label != ''),
      hint = null,
      action = null;

  /// Creates a new [CustomSemanticsAction] that overrides a standard semantics
  /// action.
  ///
  /// The [hint] must not be null or the empty string.
  const CustomSemanticsAction.overridingAction({@required this.hint, @required this.action})
    : assert(hint != null),
      assert(hint != ''),
      assert(action != null),
      label = null;

  /// The user readable name of this custom semantics action.
  final String label;

  /// The hint description of this custom semantics action.
  final String hint;

  /// The standard semantics action this action replaces.
  final SemanticsAction action;

  @override
  int get hashCode => ui.hashValues(label, hint, action);

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType)
      return false;
    return other is CustomSemanticsAction
        && other.label == label
        && other.hint == hint
        && other.action == action;
  }

  @override
  String toString() {
    return 'CustomSemanticsAction(${_ids[this]}, label:$label, hint:$hint, action:$action)';
  }

  // Logic to assign a unique id to each custom action without requiring
  // user specification.
  static int _nextId = 0;
  static final Map<int, CustomSemanticsAction> _actions = <int, CustomSemanticsAction>{};
  static final Map<CustomSemanticsAction, int> _ids = <CustomSemanticsAction, int>{};

  /// Get the identifier for a given `action`.
  static int getIdentifier(CustomSemanticsAction action) {
    int result = _ids[action];
    if (result == null) {
      result = _nextId++;
      _ids[action] = result;
      _actions[result] = action;
    }
    return result;
  }

  /// Get the `action` for a given identifier.
  static CustomSemanticsAction getAction(int id) {
    return _actions[id];
  }
}

/// Summary information about a [SemanticsNode] object.
///
/// A semantics node might [SemanticsNode.mergeAllDescendantsIntoThisNode],
/// which means the individual fields on the semantics node don't fully describe
/// the semantics at that node. This data structure contains the full semantics
/// for the node.
///
/// Typically obtained from [SemanticsNode.getSemanticsData].
@immutable
class SemanticsData with Diagnosticable {
  /// Creates a semantics data object.
  ///
  /// The [flags], [actions], [label], and [Rect] arguments must not be null.
  ///
  /// If [label] is not empty, then [textDirection] must also not be null.
  const SemanticsData({
    @required this.flags,
    @required this.actions,
    @required this.label,
    @required this.increasedValue,
    @required this.value,
    @required this.decreasedValue,
    @required this.hint,
    @required this.textDirection,
    @required this.rect,
    @required this.elevation,
    @required this.thickness,
    @required this.textSelection,
    @required this.scrollIndex,
    @required this.scrollChildCount,
    @required this.scrollPosition,
    @required this.scrollExtentMax,
    @required this.scrollExtentMin,
    @required this.platformViewId,
    @required this.maxValueLength,
    @required this.currentValueLength,
    this.tags,
    this.transform,
    this.customSemanticsActionIds,
  }) : assert(flags != null),
       assert(actions != null),
       assert(label != null),
       assert(value != null),
       assert(decreasedValue != null),
       assert(increasedValue != null),
       assert(hint != null),
       assert(label == '' || textDirection != null, 'A SemanticsData object with label "$label" had a null textDirection.'),
       assert(value == '' || textDirection != null, 'A SemanticsData object with value "$value" had a null textDirection.'),
       assert(hint == '' || textDirection != null, 'A SemanticsData object with hint "$hint" had a null textDirection.'),
       assert(decreasedValue == '' || textDirection != null, 'A SemanticsData object with decreasedValue "$decreasedValue" had a null textDirection.'),
       assert(increasedValue == '' || textDirection != null, 'A SemanticsData object with increasedValue "$increasedValue" had a null textDirection.'),
       assert(rect != null);

  /// A bit field of [SemanticsFlag]s that apply to this node.
  final int flags;

  /// A bit field of [SemanticsAction]s that apply to this node.
  final int actions;

  /// A textual description of this node.
  ///
  /// The reading direction is given by [textDirection].
  final String label;

  /// A textual description for the current value of the node.
  ///
  /// The reading direction is given by [textDirection].
  final String value;

  /// The value that [value] will become after performing a
  /// [SemanticsAction.increase] action.
  ///
  /// The reading direction is given by [textDirection].
  final String increasedValue;

  /// The value that [value] will become after performing a
  /// [SemanticsAction.decrease] action.
  ///
  /// The reading direction is given by [textDirection].
  final String decreasedValue;

  /// A brief description of the result of performing an action on this node.
  ///
  /// The reading direction is given by [textDirection].
  final String hint;

  /// The reading direction for the text in [label], [value], [hint],
  /// [increasedValue], and [decreasedValue].
  final TextDirection textDirection;

  /// The currently selected text (or the position of the cursor) within [value]
  /// if this node represents a text field.
  final TextSelection textSelection;

  /// The total number of scrollable children that contribute to semantics.
  ///
  /// If the number of children are unknown or unbounded, this value will be
  /// null.
  final int scrollChildCount;

  /// The index of the first visible semantic child of a scroll node.
  final int scrollIndex;

  /// Indicates the current scrolling position in logical pixels if the node is
  /// scrollable.
  ///
  /// The properties [scrollExtentMin] and [scrollExtentMax] indicate the valid
  /// in-range values for this property. The value for [scrollPosition] may
  /// (temporarily) be outside that range, e.g. during an overscroll.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.pixels], from where this value is usually taken.
  final double scrollPosition;

  /// Indicates the maximum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.maxScrollExtent], from where this value is usually taken.
  final double scrollExtentMax;

  /// Indicates the minimum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.minScrollExtent], from where this value is usually taken.
  final double scrollExtentMin;

  /// The id of the platform view, whose semantics nodes will be added as
  /// children to this node.
  ///
  /// If this value is non-null, the SemanticsNode must not have any children
  /// as those would be replaced by the semantics nodes of the referenced
  /// platform view.
  ///
  /// See also:
  ///
  ///  * [AndroidView], which is the platform view for Android.
  ///  * [UiKitView], which is the platform view for iOS.
  final int platformViewId;

  /// The maximum number of characters that can be entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [SemanticsFlag.isTextField] is set. Defaults
  /// to null, which means no limit is imposed on the text field.
  final int maxValueLength;

  /// The current number of characters that have been entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [SemanticsFlag.isTextField] is set. This must
  /// be set when [maxValueLength] is set.
  final int currentValueLength;

  /// The bounding box for this node in its coordinate system.
  final Rect rect;

  /// The set of [SemanticsTag]s associated with this node.
  final Set<SemanticsTag> tags;

  /// The transform from this node's coordinate system to its parent's coordinate system.
  ///
  /// By default, the transform is null, which represents the identity
  /// transformation (i.e., that this node has the same coordinate system as its
  /// parent).
  final Matrix4 transform;

  /// The elevation of this node relative to the parent semantics node.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.elevation] for a detailed discussion regarding
  ///    elevation and semantics.
  final double elevation;

  /// The extent of this node along the z-axis beyond its [elevation]
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.thickness] for a more detailed definition.
  final double thickness;

  /// The identifiers for the custom semantics actions and standard action
  /// overrides for this node.
  ///
  /// The list must be sorted in increasing order.
  ///
  /// See also:
  ///
  ///  * [CustomSemanticsAction], for an explanation of custom actions.
  final List<int> customSemanticsActionIds;

  /// Whether [flags] contains the given flag.
  bool hasFlag(SemanticsFlag flag) => (flags & flag.index) != 0;

  /// Whether [actions] contains the given action.
  bool hasAction(SemanticsAction action) => (actions & action.index) != 0;

  @override
  String toStringShort() => objectRuntimeType(this, 'SemanticsData');

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<Rect>('rect', rect, showName: false));
    properties.add(TransformProperty('transform', transform, showName: false, defaultValue: null));
    properties.add(DoubleProperty('elevation', elevation, defaultValue: 0.0));
    properties.add(DoubleProperty('thickness', thickness, defaultValue: 0.0));
    final List<String> actionSummary = <String>[
      for (final SemanticsAction action in SemanticsAction.values.values)
        if ((actions & action.index) != 0)
          describeEnum(action),
    ];
    final List<String> customSemanticsActionSummary = customSemanticsActionIds
      .map<String>((int actionId) => CustomSemanticsAction.getAction(actionId).label)
      .toList();
    properties.add(IterableProperty<String>('actions', actionSummary, ifEmpty: null));
    properties.add(IterableProperty<String>('customActions', customSemanticsActionSummary, ifEmpty: null));

    final List<String> flagSummary = <String>[
      for (final SemanticsFlag flag in SemanticsFlag.values.values)
        if ((flags & flag.index) != 0)
          describeEnum(flag),
    ];
    properties.add(IterableProperty<String>('flags', flagSummary, ifEmpty: null));
    properties.add(StringProperty('label', label, defaultValue: ''));
    properties.add(StringProperty('value', value, defaultValue: ''));
    properties.add(StringProperty('increasedValue', increasedValue, defaultValue: ''));
    properties.add(StringProperty('decreasedValue', decreasedValue, defaultValue: ''));
    properties.add(StringProperty('hint', hint, defaultValue: ''));
    properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
    if (textSelection?.isValid == true)
      properties.add(MessageProperty('textSelection', '[${textSelection.start}, ${textSelection.end}]'));
    properties.add(IntProperty('platformViewId', platformViewId, defaultValue: null));
    properties.add(IntProperty('maxValueLength', maxValueLength, defaultValue: null));
    properties.add(IntProperty('currentValueLength', currentValueLength, defaultValue: null));
    properties.add(IntProperty('scrollChildren', scrollChildCount, defaultValue: null));
    properties.add(IntProperty('scrollIndex', scrollIndex, defaultValue: null));
    properties.add(DoubleProperty('scrollExtentMin', scrollExtentMin, defaultValue: null));
    properties.add(DoubleProperty('scrollPosition', scrollPosition, defaultValue: null));
    properties.add(DoubleProperty('scrollExtentMax', scrollExtentMax, defaultValue: null));
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticsData
        && other.flags == flags
        && other.actions == actions
        && other.label == label
        && other.value == value
        && other.increasedValue == increasedValue
        && other.decreasedValue == decreasedValue
        && other.hint == hint
        && other.textDirection == textDirection
        && other.rect == rect
        && setEquals(other.tags, tags)
        && other.scrollChildCount == scrollChildCount
        && other.scrollIndex == scrollIndex
        && other.textSelection == textSelection
        && other.scrollPosition == scrollPosition
        && other.scrollExtentMax == scrollExtentMax
        && other.scrollExtentMin == scrollExtentMin
        && other.platformViewId == platformViewId
        && other.maxValueLength == maxValueLength
        && other.currentValueLength == currentValueLength
        && other.transform == transform
        && other.elevation == elevation
        && other.thickness == thickness
        && _sortedListsEqual(other.customSemanticsActionIds, customSemanticsActionIds);
  }

  @override
  int get hashCode {
    return ui.hashValues(
      ui.hashValues(
        flags,
        actions,
        label,
        value,
        increasedValue,
        decreasedValue,
        hint,
        textDirection,
        rect,
        tags,
        textSelection,
        scrollChildCount,
        scrollIndex,
        scrollPosition,
        scrollExtentMax,
        scrollExtentMin,
        platformViewId,
        maxValueLength,
        currentValueLength,
        transform,
      ),
      elevation,
      thickness,
      ui.hashList(customSemanticsActionIds),
    );
  }

  static bool _sortedListsEqual(List<int> left, List<int> right) {
    if (left == null && right == null)
      return true;
    if (left != null && right != null) {
      if (left.length != right.length)
        return false;
      for (int i = 0; i < left.length; i++)
        if (left[i] != right[i])
          return false;
      return true;
    }
    return false;
  }
}

class _SemanticsDiagnosticableNode extends DiagnosticableNode<SemanticsNode> {
  _SemanticsDiagnosticableNode({
    String name,
    @required SemanticsNode value,
    @required DiagnosticsTreeStyle style,
    @required this.childOrder,
  }) : super(
    name: name,
    value: value,
    style: style,
  );

  final DebugSemanticsDumpOrder childOrder;

  @override
  List<DiagnosticsNode> getChildren() {
    if (value != null)
      return value.debugDescribeChildren(childOrder: childOrder);

    return const <DiagnosticsNode>[];
  }
}

/// Provides hint values which override the default hints on supported
/// platforms.
///
/// On iOS, these values are always ignored.
@immutable
class SemanticsHintOverrides extends DiagnosticableTree {
  /// Creates a semantics hint overrides.
  const SemanticsHintOverrides({
    this.onTapHint,
    this.onLongPressHint,
  }) : assert(onTapHint != ''),
       assert(onLongPressHint != '');

  /// The hint text for a tap action.
  ///
  /// If null, the standard hint is used instead.
  ///
  /// The hint should describe what happens when a tap occurs, not the
  /// manner in which a tap is accomplished.
  ///
  /// Bad: 'Double tap to show movies'.
  /// Good: 'show movies'.
  final String onTapHint;

  /// The hint text for a long press action.
  ///
  /// If null, the standard hint is used instead.
  ///
  /// The hint should describe what happens when a long press occurs, not
  /// the manner in which the long press is accomplished.
  ///
  /// Bad: 'Double tap and hold to show tooltip'.
  /// Good: 'show tooltip'.
  final String onLongPressHint;

  /// Whether there are any non-null hint values.
  bool get isNotEmpty => onTapHint != null || onLongPressHint != null;

  @override
  int get hashCode => ui.hashValues(onTapHint, onLongPressHint);

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType)
      return false;
    return other is SemanticsHintOverrides
        && other.onTapHint == onTapHint
        && other.onLongPressHint == onLongPressHint;
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('onTapHint', onTapHint, defaultValue: null));
    properties.add(StringProperty('onLongPressHint', onLongPressHint, defaultValue: null));
  }
}

/// Contains properties used by assistive technologies to make the application
/// more accessible.
///
/// The properties of this class are used to generate a [SemanticsNode]s in the
/// semantics tree.
@immutable
class SemanticsProperties extends DiagnosticableTree {
  /// Creates a semantic annotation.
  const SemanticsProperties({
    this.enabled,
    this.checked,
    this.selected,
    this.toggled,
    this.button,
    this.link,
    this.header,
    this.textField,
    this.readOnly,
    this.focusable,
    this.focused,
    this.inMutuallyExclusiveGroup,
    this.hidden,
    this.obscured,
    this.multiline,
    this.scopesRoute,
    this.namesRoute,
    this.image,
    this.liveRegion,
    this.maxValueLength,
    this.currentValueLength,
    this.label,
    this.value,
    this.increasedValue,
    this.decreasedValue,
    this.hint,
    this.hintOverrides,
    this.textDirection,
    this.sortKey,
    this.onTap,
    this.onLongPress,
    this.onScrollLeft,
    this.onScrollRight,
    this.onScrollUp,
    this.onScrollDown,
    this.onIncrease,
    this.onDecrease,
    this.onCopy,
    this.onCut,
    this.onPaste,
    this.onMoveCursorForwardByCharacter,
    this.onMoveCursorBackwardByCharacter,
    this.onMoveCursorForwardByWord,
    this.onMoveCursorBackwardByWord,
    this.onSetSelection,
    this.onDidGainAccessibilityFocus,
    this.onDidLoseAccessibilityFocus,
    this.onDismiss,
    this.customSemanticsActions,
  });

  /// If non-null, indicates that this subtree represents something that can be
  /// in an enabled or disabled state.
  ///
  /// For example, a button that a user can currently interact with would set
  /// this field to true. A button that currently does not respond to user
  /// interactions would set this field to false.
  final bool enabled;

  /// If non-null, indicates that this subtree represents a checkbox
  /// or similar widget with a "checked" state, and what its current
  /// state is.
  ///
  /// This is mutually exclusive with [toggled].
  final bool checked;

  /// If non-null, indicates that this subtree represents a toggle switch
  /// or similar widget with an "on" state, and what its current
  /// state is.
  ///
  /// This is mutually exclusive with [checked].
  final bool toggled;

  /// If non-null indicates that this subtree represents something that can be
  /// in a selected or unselected state, and what its current state is.
  ///
  /// The active tab in a tab bar for example is considered "selected", whereas
  /// all other tabs are unselected.
  final bool selected;

  /// If non-null, indicates that this subtree represents a button.
  ///
  /// TalkBack/VoiceOver provides users with the hint "button" when a button
  /// is focused.
  final bool button;

  /// If non-null, indicates that this subtree represents a link.
  ///
  /// iOS's VoiceOver provides users with a unique hint when a link is focused.
  /// Android's Talkback will announce a link hint the same way it does a
  /// button.
  final bool link;

  /// If non-null, indicates that this subtree represents a header.
  ///
  /// A header divides into sections. For example, an address book application
  /// might define headers A, B, C, etc. to divide the list of alphabetically
  /// sorted contacts into sections.
  final bool header;

  /// If non-null, indicates that this subtree represents a text field.
  ///
  /// TalkBack/VoiceOver provide special affordances to enter text into a
  /// text field.
  final bool textField;

  /// If non-null, indicates that this subtree is read only.
  ///
  /// Only applicable when [textField] is true
  ///
  /// TalkBack/VoiceOver will treat it as non-editable text field.
  final bool readOnly;

  /// If non-null, whether the node is able to hold input focus.
  ///
  /// If [focusable] is set to false, then [focused] must not be true.
  ///
  /// Input focus indicates that the node will receive keyboard events. It is not
  /// to be confused with accessibility focus. Accessibility focus is the
  /// green/black rectangular highlight that TalkBack/VoiceOver draws around the
  /// element it is reading, and is separate from input focus.
  final bool focusable;

  /// If non-null, whether the node currently holds input focus.
  ///
  /// At most one node in the tree should hold input focus at any point in time,
  /// and it should not be set to true if [focusable] is false.
  ///
  /// Input focus indicates that the node will receive keyboard events. It is not
  /// to be confused with accessibility focus. Accessibility focus is the
  /// green/black rectangular highlight that TalkBack/VoiceOver draws around the
  /// element it is reading, and is separate from input focus.
  final bool focused;

  /// If non-null, whether a semantic node is in a mutually exclusive group.
  ///
  /// For example, a radio button is in a mutually exclusive group because only
  /// one radio button in that group can be marked as [checked].
  final bool inMutuallyExclusiveGroup;

  /// If non-null, whether the node is considered hidden.
  ///
  /// Hidden elements are currently not visible on screen. They may be covered
  /// by other elements or positioned outside of the visible area of a viewport.
  ///
  /// Hidden elements cannot gain accessibility focus though regular touch. The
  /// only way they can be focused is by moving the focus to them via linear
  /// navigation.
  ///
  /// Platforms are free to completely ignore hidden elements and new platforms
  /// are encouraged to do so.
  ///
  /// Instead of marking an element as hidden it should usually be excluded from
  /// the semantics tree altogether. Hidden elements are only included in the
  /// semantics tree to work around platform limitations and they are mainly
  /// used to implement accessibility scrolling on iOS.
  final bool hidden;

  /// If non-null, whether [value] should be obscured.
  ///
  /// This option is usually set in combination with [textField] to indicate
  /// that the text field contains a password (or other sensitive information).
  /// Doing so instructs screen readers to not read out the [value].
  final bool obscured;

  /// Whether the [value] is coming from a field that supports multiline text
  /// editing.
  ///
  /// This option is only meaningful when [textField] is true to indicate
  /// whether it's a single-line or multiline text field.
  ///
  /// This option is null when [textField] is false.
  final bool multiline;

  /// If non-null, whether the node corresponds to the root of a subtree for
  /// which a route name should be announced.
  ///
  /// Generally, this is set in combination with [explicitChildNodes], since
  /// nodes with this flag are not considered focusable by Android or iOS.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.scopesRoute] for a description of how the announced
  ///    value is selected.
  final bool scopesRoute;

  /// If non-null, whether the node contains the semantic label for a route.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.namesRoute] for a description of how the name is used.
  final bool namesRoute;

  /// If non-null, whether the node represents an image.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.image], for the flag this setting controls.
  final bool image;

  /// If non-null, whether the node should be considered a live region.
  ///
  /// On Android, when the label changes on a live region semantics node,
  /// TalkBack will make a polite announcement of the current label. This
  /// announcement occurs even if the node is not focused, but only if the label
  /// has changed since the last update.
  ///
  /// On iOS, no announcements are made but the node is marked as
  /// `UIAccessibilityTraitUpdatesFrequently`.
  ///
  /// An example of a live region is the [Snackbar] widget. When it appears
  /// on the screen it may be difficult to focus to read the label. A live
  /// region causes an initial polite announcement to be generated
  /// automatically.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.liveRegion], the semantics flag this setting controls.
  ///  * [SemanticsConfiguration.liveRegion], for a full description of a live region.
  final bool liveRegion;

  /// The maximum number of characters that can be entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [textField] is true. Defaults to null,
  /// which means no limit is imposed on the text field.
  final int maxValueLength;

  /// The current number of characters that have been entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [textField] is true. Must be set when
  /// [maxValueLength] is set.
  final int currentValueLength;

  /// Provides a textual description of the widget.
  ///
  /// If a label is provided, there must either by an ambient [Directionality]
  /// or an explicit [textDirection] should be provided.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.label] for a description of how this is exposed
  ///    in TalkBack and VoiceOver.
  final String label;

  /// Provides a textual description of the value of the widget.
  ///
  /// If a value is provided, there must either by an ambient [Directionality]
  /// or an explicit [textDirection] should be provided.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.value] for a description of how this is exposed
  ///    in TalkBack and VoiceOver.
  final String value;

  /// The value that [value] will become after a [SemanticsAction.increase]
  /// action has been performed on this widget.
  ///
  /// If a value is provided, [onIncrease] must also be set and there must
  /// either be an ambient [Directionality] or an explicit [textDirection]
  /// must be provided.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.increasedValue] for a description of how this
  ///    is exposed in TalkBack and VoiceOver.
  final String increasedValue;

  /// The value that [value] will become after a [SemanticsAction.decrease]
  /// action has been performed on this widget.
  ///
  /// If a value is provided, [onDecrease] must also be set and there must
  /// either be an ambient [Directionality] or an explicit [textDirection]
  /// must be provided.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.decreasedValue] for a description of how this
  ///    is exposed in TalkBack and VoiceOver.
  final String decreasedValue;

  /// Provides a brief textual description of the result of an action performed
  /// on the widget.
  ///
  /// If a hint is provided, there must either be an ambient [Directionality]
  /// or an explicit [textDirection] should be provided.
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.hint] for a description of how this is exposed
  ///    in TalkBack and VoiceOver.
  final String hint;

  /// Provides hint values which override the default hints on supported
  /// platforms.
  ///
  /// On Android, If no hint overrides are used then default [hint] will be
  /// combined with the [label]. Otherwise, the [hint] will be ignored as long
  /// as there as at least one non-null hint override.
  ///
  /// On iOS, these are always ignored and the default [hint] is used instead.
  final SemanticsHintOverrides hintOverrides;

  /// The reading direction of the [label], [value], [hint], [increasedValue],
  /// and [decreasedValue].
  ///
  /// Defaults to the ambient [Directionality].
  final TextDirection textDirection;

  /// Determines the position of this node among its siblings in the traversal
  /// sort order.
  ///
  /// This is used to describe the order in which the semantic node should be
  /// traversed by the accessibility services on the platform (e.g. VoiceOver
  /// on iOS and TalkBack on Android).
  final SemanticsSortKey sortKey;

  /// The handler for [SemanticsAction.tap].
  ///
  /// This is the semantic equivalent of a user briefly tapping the screen with
  /// the finger without moving it. For example, a button should implement this
  /// action.
  ///
  /// VoiceOver users on iOS and TalkBack users on Android can trigger this
  /// action by double-tapping the screen while an element is focused.
  final VoidCallback onTap;

  /// The handler for [SemanticsAction.longPress].
  ///
  /// This is the semantic equivalent of a user pressing and holding the screen
  /// with the finger for a few seconds without moving it.
  ///
  /// VoiceOver users on iOS and TalkBack users on Android can trigger this
  /// action by double-tapping the screen without lifting the finger after the
  /// second tap.
  final VoidCallback onLongPress;

  /// The handler for [SemanticsAction.scrollLeft].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from right to left. It should be recognized by controls that are
  /// horizontally scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping left with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// right and then left in one motion path. On Android, [onScrollUp] and
  /// [onScrollLeft] share the same gesture. Therefore, only on of them should
  /// be provided.
  final VoidCallback onScrollLeft;

  /// The handler for [SemanticsAction.scrollRight].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from left to right. It should be recognized by controls that are
  /// horizontally scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping right with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// left and then right in one motion path. On Android, [onScrollDown] and
  /// [onScrollRight] share the same gesture. Therefore, only on of them should
  /// be provided.
  final VoidCallback onScrollRight;

  /// The handler for [SemanticsAction.scrollUp].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from bottom to top. It should be recognized by controls that are
  /// vertically scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping up with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// right and then left in one motion path. On Android, [onScrollUp] and
  /// [onScrollLeft] share the same gesture. Therefore, only on of them should
  /// be provided.
  final VoidCallback onScrollUp;

  /// The handler for [SemanticsAction.scrollDown].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from top to bottom. It should be recognized by controls that are
  /// vertically scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping down with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// left and then right in one motion path. On Android, [onScrollDown] and
  /// [onScrollRight] share the same gesture. Therefore, only on of them should
  /// be provided.
  final VoidCallback onScrollDown;

  /// The handler for [SemanticsAction.increase].
  ///
  /// This is a request to increase the value represented by the widget. For
  /// example, this action might be recognized by a slider control.
  ///
  /// If a [value] is set, [increasedValue] must also be provided and
  /// [onIncrease] must ensure that [value] will be set to [increasedValue].
  ///
  /// VoiceOver users on iOS can trigger this action by swiping up with one
  /// finger. TalkBack users on Android can trigger this action by pressing the
  /// volume up button.
  final VoidCallback onIncrease;

  /// The handler for [SemanticsAction.decrease].
  ///
  /// This is a request to decrease the value represented by the widget. For
  /// example, this action might be recognized by a slider control.
  ///
  /// If a [value] is set, [decreasedValue] must also be provided and
  /// [onDecrease] must ensure that [value] will be set to [decreasedValue].
  ///
  /// VoiceOver users on iOS can trigger this action by swiping down with one
  /// finger. TalkBack users on Android can trigger this action by pressing the
  /// volume down button.
  final VoidCallback onDecrease;

  /// The handler for [SemanticsAction.copy].
  ///
  /// This is a request to copy the current selection to the clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  final VoidCallback onCopy;

  /// The handler for [SemanticsAction.cut].
  ///
  /// This is a request to cut the current selection and place it in the
  /// clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  final VoidCallback onCut;

  /// The handler for [SemanticsAction.paste].
  ///
  /// This is a request to paste the current content of the clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  final VoidCallback onPaste;

  /// The handler for [SemanticsAction.onMoveCursorForwardByCharacter].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field forward by one character.
  ///
  /// TalkBack users can trigger this by pressing the volume up key while the
  /// input focus is in a text field.
  final MoveCursorHandler onMoveCursorForwardByCharacter;

  /// The handler for [SemanticsAction.onMoveCursorBackwardByCharacter].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one character.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  final MoveCursorHandler onMoveCursorBackwardByCharacter;

  /// The handler for [SemanticsAction.onMoveCursorForwardByWord].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one word.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  final MoveCursorHandler onMoveCursorForwardByWord;

  /// The handler for [SemanticsAction.onMoveCursorBackwardByWord].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one word.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  final MoveCursorHandler onMoveCursorBackwardByWord;

  /// The handler for [SemanticsAction.setSelection].
  ///
  /// This handler is invoked when the user either wants to change the currently
  /// selected text in a text field or change the position of the cursor.
  ///
  /// TalkBack users can trigger this handler by selecting "Move cursor to
  /// beginning/end" or "Select all" from the local context menu.
  final SetSelectionHandler onSetSelection;

  /// The handler for [SemanticsAction.didGainAccessibilityFocus].
  ///
  /// This handler is invoked when the node annotated with this handler gains
  /// the accessibility focus. The accessibility focus is the
  /// green (on Android with TalkBack) or black (on iOS with VoiceOver)
  /// rectangle shown on screen to indicate what element an accessibility
  /// user is currently interacting with.
  ///
  /// The accessibility focus is different from the input focus. The input focus
  /// is usually held by the element that currently responds to keyboard inputs.
  /// Accessibility focus and input focus can be held by two different nodes!
  ///
  /// See also:
  ///
  ///  * [onDidLoseAccessibilityFocus], which is invoked when the accessibility
  ///    focus is removed from the node.
  ///  * [FocusNode], [FocusScope], [FocusManager], which manage the input focus.
  final VoidCallback onDidGainAccessibilityFocus;

  /// The handler for [SemanticsAction.didLoseAccessibilityFocus].
  ///
  /// This handler is invoked when the node annotated with this handler
  /// loses the accessibility focus. The accessibility focus is
  /// the green (on Android with TalkBack) or black (on iOS with VoiceOver)
  /// rectangle shown on screen to indicate what element an accessibility
  /// user is currently interacting with.
  ///
  /// The accessibility focus is different from the input focus. The input focus
  /// is usually held by the element that currently responds to keyboard inputs.
  /// Accessibility focus and input focus can be held by two different nodes!
  ///
  /// See also:
  ///
  ///  * [onDidGainAccessibilityFocus], which is invoked when the node gains
  ///    accessibility focus.
  ///  * [FocusNode], [FocusScope], [FocusManager], which manage the input focus.
  final VoidCallback onDidLoseAccessibilityFocus;

  /// The handler for [SemanticsAction.dismiss].
  ///
  /// This is a request to dismiss the currently focused node.
  ///
  /// TalkBack users on Android can trigger this action in the local context
  /// menu, and VoiceOver users on iOS can trigger this action with a standard
  /// gesture or menu option.
  final VoidCallback onDismiss;

  /// A map from each supported [CustomSemanticsAction] to a provided handler.
  ///
  /// The handler associated with each custom action is called whenever a
  /// semantics event of type [SemanticsEvent.customEvent] is received. The
  /// provided argument will be an identifier used to retrieve an instance of
  /// a custom action which can then retrieve the correct handler from this map.
  ///
  /// See also:
  ///
  ///  * [CustomSemanticsAction], for an explanation of custom actions.
  final Map<CustomSemanticsAction, VoidCallback> customSemanticsActions;

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<bool>('checked', checked, defaultValue: null));
    properties.add(DiagnosticsProperty<bool>('selected', selected, defaultValue: null));
    properties.add(StringProperty('label', label, defaultValue: ''));
    properties.add(StringProperty('value', value));
    properties.add(StringProperty('hint', hint));
    properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
    properties.add(DiagnosticsProperty<SemanticsSortKey>('sortKey', sortKey, defaultValue: null));
    properties.add(DiagnosticsProperty<SemanticsHintOverrides>('hintOverrides', hintOverrides));
  }

  @override
  String toStringShort() => objectRuntimeType(this, 'SemanticsProperties'); // the hashCode isn't important since we're immutable
}

/// In tests use this function to reset the counter used to generate
/// [SemanticsNode.id].
void debugResetSemanticsIdCounter() {
  SemanticsNode._lastIdentifier = 0;
}

/// A node that represents some semantic data.
///
/// The semantics tree is maintained during the semantics phase of the pipeline
/// (i.e., during [PipelineOwner.flushSemantics]), which happens after
/// compositing. The semantics tree is then uploaded into the engine for use
/// by assistive technology.
class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
  /// Creates a semantic node.
  ///
  /// Each semantic node has a unique identifier that is assigned when the node
  /// is created.
  SemanticsNode({
    this.key,
    VoidCallback showOnScreen,
  }) : id = _generateNewId(),
       _showOnScreen = showOnScreen;

  /// Creates a semantic node to represent the root of the semantics tree.
  ///
  /// The root node is assigned an identifier of zero.
  SemanticsNode.root({
    this.key,
    VoidCallback showOnScreen,
    SemanticsOwner owner,
  }) : id = 0,
       _showOnScreen = showOnScreen {
    attach(owner);
  }


  // The maximal semantic node identifier generated by the framework.
  //
  // The identifier range for semantic node IDs is split into 2, the least significant 16 bits are
  // reserved for framework generated IDs(generated with _generateNewId), and most significant 32
  // bits are reserved for engine generated IDs.
  static const int _maxFrameworkAccessibilityIdentifier = (1<<16) - 1;

  static int _lastIdentifier = 0;
  static int _generateNewId() {
    _lastIdentifier = (_lastIdentifier + 1) % _maxFrameworkAccessibilityIdentifier;
    return _lastIdentifier;
  }

  /// Uniquely identifies this node in the list of sibling nodes.
  ///
  /// Keys are used during the construction of the semantics tree. They are not
  /// transferred to the engine.
  final Key key;

  /// The unique identifier for this node.
  ///
  /// The root node has an id of zero. Other nodes are given a unique id when
  /// they are created.
  final int id;

  final VoidCallback _showOnScreen;

  // GEOMETRY

  /// The transform from this node's coordinate system to its parent's coordinate system.
  ///
  /// By default, the transform is null, which represents the identity
  /// transformation (i.e., that this node has the same coordinate system as its
  /// parent).
  Matrix4 get transform => _transform;
  Matrix4 _transform;
  set transform(Matrix4 value) {
    if (!MatrixUtils.matrixEquals(_transform, value)) {
      _transform = MatrixUtils.isIdentity(value) ? null : value;
      _markDirty();
    }
  }

  /// The bounding box for this node in its coordinate system.
  Rect get rect => _rect;
  Rect _rect = Rect.zero;
  set rect(Rect value) {
    assert(value != null);
    assert(value.isFinite, '$this (with $owner) tried to set a non-finite rect.');
    if (_rect != value) {
      _rect = value;
      _markDirty();
    }
  }

  /// The semantic clip from an ancestor that was applied to this node.
  ///
  /// Expressed in the coordinate system of the node. May be null if no clip has
  /// been applied.
  ///
  /// Descendant [SemanticsNode]s that are positioned outside of this rect will
  /// be excluded from the semantics tree. Descendant [SemanticsNode]s that are
  /// overlapping with this rect, but are outside of [parentPaintClipRect] will
  /// be included in the tree, but they will be marked as hidden because they
  /// are assumed to be not visible on screen.
  ///
  /// If this rect is null, all descendant [SemanticsNode]s outside of
  /// [parentPaintClipRect] will be excluded from the tree.
  ///
  /// If this rect is non-null it has to completely enclose
  /// [parentPaintClipRect]. If [parentPaintClipRect] is null this property is
  /// also null.
  Rect parentSemanticsClipRect;

  /// The paint clip from an ancestor that was applied to this node.
  ///
  /// Expressed in the coordinate system of the node. May be null if no clip has
  /// been applied.
  ///
  /// Descendant [SemanticsNode]s that are positioned outside of this rect will
  /// either be excluded from the semantics tree (if they have no overlap with
  /// [parentSemanticsClipRect]) or they will be included and marked as hidden
  /// (if they are overlapping with [parentSemanticsClipRect]).
  ///
  /// This rect is completely enclosed by [parentSemanticsClipRect].
  ///
  /// If this rect is null [parentSemanticsClipRect] also has to be null.
  Rect parentPaintClipRect;

  /// The elevation adjustment that the parent imposes on this node.
  ///
  /// The [elevation] property is relative to the elevation of the parent
  /// [SemanticsNode]. However, as [SemanticsConfiguration]s from various
  /// ascending [RenderObjects] are merged into each other to form that
  /// [SemanticsNode] the parent’s elevation may change. This requires an
  /// adjustment of the child’s relative elevation which is represented by this
  /// value.
  ///
  /// The value is rarely accessed directly. Instead, for most use cases the
  /// [elevation] value should be used, which includes this adjustment.
  ///
  /// See also:
  ///
  ///  * [elevation], the actual elevation of this [SemanticsNode].
  double elevationAdjustment;

  /// The index of this node within the parent's list of semantic children.
  ///
  /// This includes all semantic nodes, not just those currently in the
  /// child list. For example, if a scrollable has five children but the first
  /// two are not visible (and thus not included in the list of children), then
  /// the index of the last node will still be 4.
  int indexInParent;

  /// Whether the node is invisible.
  ///
  /// A node whose [rect] is outside of the bounds of the screen and hence not
  /// reachable for users is considered invisible if its semantic information
  /// is not merged into a (partially) visible parent as indicated by
  /// [isMergedIntoParent].
  ///
  /// An invisible node can be safely dropped from the semantic tree without
  /// loosing semantic information that is relevant for describing the content
  /// currently shown on screen.
  bool get isInvisible => !isMergedIntoParent && rect.isEmpty;

  // MERGING

  /// Whether this node merges its semantic information into an ancestor node.
  bool get isMergedIntoParent => _isMergedIntoParent;
  bool _isMergedIntoParent = false;
  set isMergedIntoParent(bool value) {
    assert(value != null);
    if (_isMergedIntoParent == value)
      return;
    _isMergedIntoParent = value;
    _markDirty();
  }

  /// Whether this node is taking part in a merge of semantic information.
  ///
  /// This returns true if the node is either merged into an ancestor node or if
  /// decedent nodes are merged into this node.
  ///
  /// See also:
  ///
  ///  * [isMergedIntoParent]
  ///  * [mergeAllDescendantsIntoThisNode]
  bool get isPartOfNodeMerging => mergeAllDescendantsIntoThisNode || isMergedIntoParent;

  /// Whether this node and all of its descendants should be treated as one logical entity.
  bool get mergeAllDescendantsIntoThisNode => _mergeAllDescendantsIntoThisNode;
  bool _mergeAllDescendantsIntoThisNode = _kEmptyConfig.isMergingSemanticsOfDescendants;


  // CHILDREN

  /// Contains the children in inverse hit test order (i.e. paint order).
  List<SemanticsNode> _children;

  /// A snapshot of `newChildren` passed to [_replaceChildren] that we keep in
  /// debug mode. It supports the assertion that user does not mutate the list
  /// of children.
  List<SemanticsNode> _debugPreviousSnapshot;

  void _replaceChildren(List<SemanticsNode> newChildren) {
    assert(!newChildren.any((SemanticsNode child) => child == this));
    assert(() {
      if (identical(newChildren, _children)) {
        final List<DiagnosticsNode> mutationErrors = <DiagnosticsNode>[];
        if (newChildren.length != _debugPreviousSnapshot.length) {
          mutationErrors.add(ErrorDescription(
            "The list's length has changed from ${_debugPreviousSnapshot.length} "
            'to ${newChildren.length}.'
          ));
        } else {
          for (int i = 0; i < newChildren.length; i++) {
            if (!identical(newChildren[i], _debugPreviousSnapshot[i])) {
              if (mutationErrors.isNotEmpty) {
                mutationErrors.add(ErrorSpacer());
              }
              mutationErrors.add(ErrorDescription('Child node at position $i was replaced:'));
              mutationErrors.add(newChildren[i].toDiagnosticsNode(name: 'Previous child', style: DiagnosticsTreeStyle.singleLine));
              mutationErrors.add(_debugPreviousSnapshot[i].toDiagnosticsNode(name: 'New child', style: DiagnosticsTreeStyle.singleLine));
            }
          }
        }
        if (mutationErrors.isNotEmpty) {
          throw FlutterError.fromParts(<DiagnosticsNode>[
            ErrorSummary('Failed to replace child semantics nodes because the list of `SemanticsNode`s was mutated.'),
            ErrorHint('Instead of mutating the existing list, create a new list containing the desired `SemanticsNode`s.'),
            ErrorDescription('Error details:'),
            ...mutationErrors,
          ]);
        }
      }
      assert(!newChildren.any((SemanticsNode node) => node.isMergedIntoParent) || isPartOfNodeMerging);

      _debugPreviousSnapshot = List<SemanticsNode>.from(newChildren);

      SemanticsNode ancestor = this;
      while (ancestor.parent is SemanticsNode)
        ancestor = ancestor.parent;
      assert(!newChildren.any((SemanticsNode child) => child == ancestor));
      return true;
    }());
    assert(() {
      final Set<SemanticsNode> seenChildren = <SemanticsNode>{};
      for (final SemanticsNode child in newChildren)
        assert(seenChildren.add(child)); // check for duplicate adds
      return true;
    }());

    // The goal of this function is updating sawChange.
    if (_children != null) {
      for (final SemanticsNode child in _children)
        child._dead = true;
    }
    if (newChildren != null) {
      for (final SemanticsNode child in newChildren) {
        assert(!child.isInvisible, 'Child $child is invisible and should not be added as a child of $this.');
        child._dead = false;
      }
    }
    bool sawChange = false;
    if (_children != null) {
      for (final SemanticsNode child in _children) {
        if (child._dead) {
          if (child.parent == this) {
            // we might have already had our child stolen from us by
            // another node that is deeper in the tree.
            dropChild(child);
          }
          sawChange = true;
        }
      }
    }
    if (newChildren != null) {
      for (final SemanticsNode child in newChildren) {
        if (child.parent != this) {
          if (child.parent != null) {
            // we're rebuilding the tree from the bottom up, so it's possible
            // that our child was, in the last pass, a child of one of our
            // ancestors. In that case, we drop the child eagerly here.
            // TODO(ianh): Find a way to assert that the same node didn't
            // actually appear in the tree in two places.
            child.parent?.dropChild(child);
          }
          assert(!child.attached);
          adoptChild(child);
          sawChange = true;
        }
      }
    }
    if (!sawChange && _children != null) {
      assert(newChildren != null);
      assert(newChildren.length == _children.length);
      // Did the order change?
      for (int i = 0; i < _children.length; i++) {
        if (_children[i].id != newChildren[i].id) {
          sawChange = true;
          break;
        }
      }
    }
    _children = newChildren;
    if (sawChange)
      _markDirty();
  }

  /// Whether this node has a non-zero number of children.
  bool get hasChildren => _children?.isNotEmpty ?? false;
  bool _dead = false;

  /// The number of children this node has.
  int get childrenCount => hasChildren ? _children.length : 0;

  /// Visits the immediate children of this node.
  ///
  /// This function calls visitor for each immediate child until visitor returns
  /// false. Returns true if all the visitor calls returned true, otherwise
  /// returns false.
  void visitChildren(SemanticsNodeVisitor visitor) {
    if (_children != null) {
      for (final SemanticsNode child in _children) {
        if (!visitor(child))
          return;
      }
    }
  }

  /// Visit all the descendants of this node.
  ///
  /// This function calls visitor for each descendant in a pre-order traversal
  /// until visitor returns false. Returns true if all the visitor calls
  /// returned true, otherwise returns false.
  bool _visitDescendants(SemanticsNodeVisitor visitor) {
    if (_children != null) {
      for (final SemanticsNode child in _children) {
        if (!visitor(child) || !child._visitDescendants(visitor))
          return false;
      }
    }
    return true;
  }

  // AbstractNode OVERRIDES

  @override
  SemanticsOwner get owner => super.owner as SemanticsOwner;

  @override
  SemanticsNode get parent => super.parent as SemanticsNode;

  @override
  void redepthChildren() {
    _children?.forEach(redepthChild);
  }

  @override
  void attach(SemanticsOwner owner) {
    super.attach(owner);
    assert(!owner._nodes.containsKey(id));
    owner._nodes[id] = this;
    owner._detachedNodes.remove(this);
    if (_dirty) {
      _dirty = false;
      _markDirty();
    }
    if (_children != null) {
      for (final SemanticsNode child in _children)
        child.attach(owner);
    }
  }

  @override
  void detach() {
    assert(owner._nodes.containsKey(id));
    assert(!owner._detachedNodes.contains(this));
    owner._nodes.remove(id);
    owner._detachedNodes.add(this);
    super.detach();
    assert(owner == null);
    if (_children != null) {
      for (final SemanticsNode child in _children) {
        // The list of children may be stale and may contain nodes that have
        // been assigned to a different parent.
        if (child.parent == this)
          child.detach();
      }
    }
    // The other side will have forgotten this node if we ever send
    // it again, so make sure to mark it dirty so that it'll get
    // sent if it is resurrected.
    _markDirty();
  }

  // DIRTY MANAGEMENT

  bool _dirty = false;
  void _markDirty() {
    if (_dirty)
      return;
    _dirty = true;
    if (attached) {
      assert(!owner._detachedNodes.contains(this));
      owner._dirtyNodes.add(this);
    }
  }

  bool _isDifferentFromCurrentSemanticAnnotation(SemanticsConfiguration config) {
    return _label != config.label ||
        _hint != config.hint ||
        _elevation != config.elevation ||
        _thickness != config.thickness ||
        _decreasedValue != config.decreasedValue ||
        _value != config.value ||
        _increasedValue != config.increasedValue ||
        _flags != config._flags ||
        _textDirection != config.textDirection ||
        _sortKey != config._sortKey ||
        _textSelection != config._textSelection ||
        _scrollPosition != config._scrollPosition ||
        _scrollExtentMax != config._scrollExtentMax ||
        _scrollExtentMin != config._scrollExtentMin ||
        _actionsAsBits != config._actionsAsBits ||
        indexInParent != config.indexInParent ||
        platformViewId != config.platformViewId ||
        _maxValueLength != config._maxValueLength ||
        _currentValueLength != config._currentValueLength ||
        _mergeAllDescendantsIntoThisNode != config.isMergingSemanticsOfDescendants;
  }

  // TAGS, LABELS, ACTIONS

  Map<SemanticsAction, _SemanticsActionHandler> _actions = _kEmptyConfig._actions;
  Map<CustomSemanticsAction, VoidCallback> _customSemanticsActions = _kEmptyConfig._customSemanticsActions;

  int _actionsAsBits = _kEmptyConfig._actionsAsBits;

  /// The [SemanticsTag]s this node is tagged with.
  ///
  /// Tags are used during the construction of the semantics tree. They are not
  /// transferred to the engine.
  Set<SemanticsTag> tags;

  /// Whether this node is tagged with `tag`.
  bool isTagged(SemanticsTag tag) => tags != null && tags.contains(tag);

  int _flags = _kEmptyConfig._flags;

  /// Whether this node currently has a given [SemanticsFlag].
  bool hasFlag(SemanticsFlag flag) => _flags & flag.index != 0;

  /// A textual description of this node.
  ///
  /// The reading direction is given by [textDirection].
  String get label => _label;
  String _label = _kEmptyConfig.label;

  /// A textual description for the current value of the node.
  ///
  /// The reading direction is given by [textDirection].
  String get value => _value;
  String _value = _kEmptyConfig.value;

  /// The value that [value] will have after a [SemanticsAction.decrease] action
  /// has been performed.
  ///
  /// This property is only valid if the [SemanticsAction.decrease] action is
  /// available on this node.
  ///
  /// The reading direction is given by [textDirection].
  String get decreasedValue => _decreasedValue;
  String _decreasedValue = _kEmptyConfig.decreasedValue;

  /// The value that [value] will have after a [SemanticsAction.increase] action
  /// has been performed.
  ///
  /// This property is only valid if the [SemanticsAction.increase] action is
  /// available on this node.
  ///
  /// The reading direction is given by [textDirection].
  String get increasedValue => _increasedValue;
  String _increasedValue = _kEmptyConfig.increasedValue;

  /// A brief description of the result of performing an action on this node.
  ///
  /// The reading direction is given by [textDirection].
  String get hint => _hint;
  String _hint = _kEmptyConfig.hint;

  /// The elevation along the z-axis at which the [rect] of this [SemanticsNode]
  /// is located above its parent.
  ///
  /// The value is relative to the parent's [elevation]. The sum of the
  /// [elevation]s of all ancestor node plus this value determines the absolute
  /// elevation of this [SemanticsNode].
  ///
  /// See also:
  ///
  ///  * [thickness], which describes how much space in z-direction this
  ///    [SemanticsNode] occupies starting at this [elevation].
  ///  * [elevationAdjustment], which has been used to calculate this value.
  double get elevation => _elevation;
  double _elevation = _kEmptyConfig.elevation;

  /// Describes how much space the [SemanticsNode] takes up along the z-axis.
  ///
  /// A [SemanticsNode] represents multiple [RenderObject]s, which can be
  /// located at various elevations in 3D. The [thickness] is the difference
  /// between the absolute elevations of the lowest and highest [RenderObject]
  /// represented by this [SemanticsNode]. In other words, the thickness
  /// describes how high the box is that this [SemanticsNode] occupies in three
  /// dimensional space. The two other dimensions are defined by [rect].
  ///
  /// {@tool snippet}
  /// The following code stacks three [PhysicalModel]s on top of each other
  /// separated by non-zero elevations.
  ///
  /// [PhysicalModel] C is elevated 10.0 above [PhysicalModel] B, which in turn
  /// is elevated 5.0 above [PhysicalModel] A. The side view of this
  /// constellation looks as follows:
  ///
  /// ![A diagram illustrating the elevations of three PhysicalModels and their
  /// corresponding SemanticsNodes.](https://flutter.github.io/assets-for-api-docs/assets/semantics/SemanticsNode.thickness.png)
  ///
  /// In this example the [RenderObject]s for [PhysicalModel] C and B share one
  /// [SemanticsNode] Y. Given the elevations of those [RenderObject]s, this
  /// [SemanticsNode] has a [thickness] of 10.0 and an elevation of 5.0 over
  /// its parent [SemanticsNode] X.
  /// ```dart
  /// PhysicalModel( // A
  ///   color: Colors.amber,
  ///   elevation: 0.0,
  ///   child: Semantics(
  ///     explicitChildNodes: true,
  ///     child: PhysicalModel( // B
  ///       color: Colors.brown,
  ///       elevation: 5.0,
  ///       child: PhysicalModel( // C
  ///         color: Colors.cyan,
  ///         elevation: 10.0,
  ///         child: Placeholder(),
  ///       ),
  ///     ),
  ///   ),
  /// )
  /// ```
  /// {@end-tool}
  ///
  /// See also:
  ///
  ///  * [elevation], which describes the elevation of the box defined by
  ///    [thickness] and [rect] relative to the parent of this [SemanticsNode].
  double get thickness => _thickness;
  double _thickness = _kEmptyConfig.thickness;

  /// Provides hint values which override the default hints on supported
  /// platforms.
  SemanticsHintOverrides get hintOverrides => _hintOverrides;
  SemanticsHintOverrides _hintOverrides;

  /// The reading direction for [label], [value], [hint], [increasedValue], and
  /// [decreasedValue].
  TextDirection get textDirection => _textDirection;
  TextDirection _textDirection = _kEmptyConfig.textDirection;

  /// Determines the position of this node among its siblings in the traversal
  /// sort order.
  ///
  /// This is used to describe the order in which the semantic node should be
  /// traversed by the accessibility services on the platform (e.g. VoiceOver
  /// on iOS and TalkBack on Android).
  SemanticsSortKey get sortKey => _sortKey;
  SemanticsSortKey _sortKey;

  /// The currently selected text (or the position of the cursor) within [value]
  /// if this node represents a text field.
  TextSelection get textSelection => _textSelection;
  TextSelection _textSelection;

  /// If this node represents a text field, this indicates whether or not it's
  /// a multiline text field.
  bool get isMultiline => _isMultiline;
  bool _isMultiline;

  /// The total number of scrollable children that contribute to semantics.
  ///
  /// If the number of children are unknown or unbounded, this value will be
  /// null.
  int get scrollChildCount => _scrollChildCount;
  int _scrollChildCount;

  /// The index of the first visible semantic child of a scroll node.
  int get scrollIndex => _scrollIndex;
  int _scrollIndex;

  /// Indicates the current scrolling position in logical pixels if the node is
  /// scrollable.
  ///
  /// The properties [scrollExtentMin] and [scrollExtentMax] indicate the valid
  /// in-range values for this property. The value for [scrollPosition] may
  /// (temporarily) be outside that range, e.g. during an overscroll.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.pixels], from where this value is usually taken.
  double get scrollPosition => _scrollPosition;
  double _scrollPosition;

  /// Indicates the maximum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.maxScrollExtent], from where this value is usually taken.
  double get scrollExtentMax => _scrollExtentMax;
  double _scrollExtentMax;

  /// Indicates the minimum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.minScrollExtent] from where this value is usually taken.
  double get scrollExtentMin => _scrollExtentMin;
  double _scrollExtentMin;

  /// The id of the platform view, whose semantics nodes will be added as
  /// children to this node.
  ///
  /// If this value is non-null, the SemanticsNode must not have any children
  /// as those would be replaced by the semantics nodes of the referenced
  /// platform view.
  ///
  /// See also:
  ///
  ///  * [AndroidView], which is the platform view for Android.
  ///  * [UiKitView], which is the platform view for iOS.
  int get platformViewId => _platformViewId;
  int _platformViewId;

  /// The maximum number of characters that can be entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [SemanticsFlag.isTextField] is set. Defaults
  /// to null, which means no limit is imposed on the text field.
  int get maxValueLength => _maxValueLength;
  int _maxValueLength;

  /// The current number of characters that have been entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [SemanticsFlag.isTextField] is set. Must be
  /// set when [maxValueLength] is set.
  int get currentValueLength => _currentValueLength;
  int _currentValueLength;

  bool _canPerformAction(SemanticsAction action) => _actions.containsKey(action);

  static final SemanticsConfiguration _kEmptyConfig = SemanticsConfiguration();

  /// Reconfigures the properties of this object to describe the configuration
  /// provided in the `config` argument and the children listed in the
  /// `childrenInInversePaintOrder` argument.
  ///
  /// The arguments may be null; this represents an empty configuration (all
  /// values at their defaults, no children).
  ///
  /// No reference is kept to the [SemanticsConfiguration] object, but the child
  /// list is used as-is and should therefore not be changed after this call.
  void updateWith({
    @required SemanticsConfiguration config,
    List<SemanticsNode> childrenInInversePaintOrder,
  }) {
    config ??= _kEmptyConfig;
    if (_isDifferentFromCurrentSemanticAnnotation(config))
      _markDirty();

    assert(
      config.platformViewId == null || childrenInInversePaintOrder.isEmpty,
      'SemanticsNodes with children must not specify a platformViewId.'
    );

    _label = config.label;
    _decreasedValue = config.decreasedValue;
    _value = config.value;
    _increasedValue = config.increasedValue;
    _hint = config.hint;
    _hintOverrides = config.hintOverrides;
    _elevation = config.elevation;
    _thickness = config.thickness;
    _flags = config._flags;
    _textDirection = config.textDirection;
    _sortKey = config.sortKey;
    _actions = Map<SemanticsAction, _SemanticsActionHandler>.from(config._actions);
    _customSemanticsActions = Map<CustomSemanticsAction, VoidCallback>.from(config._customSemanticsActions);
    _actionsAsBits = config._actionsAsBits;
    _textSelection = config._textSelection;
    _isMultiline = config.isMultiline;
    _scrollPosition = config._scrollPosition;
    _scrollExtentMax = config._scrollExtentMax;
    _scrollExtentMin = config._scrollExtentMin;
    _mergeAllDescendantsIntoThisNode = config.isMergingSemanticsOfDescendants;
    _scrollChildCount = config.scrollChildCount;
    _scrollIndex = config.scrollIndex;
    indexInParent = config.indexInParent;
    _platformViewId = config._platformViewId;
    _maxValueLength = config._maxValueLength;
    _currentValueLength = config._currentValueLength;
    _replaceChildren(childrenInInversePaintOrder ?? const <SemanticsNode>[]);

    assert(
      !_canPerformAction(SemanticsAction.increase) || (_value == '') == (_increasedValue == ''),
      'A SemanticsNode with action "increase" needs to be annotated with either both "value" and "increasedValue" or neither',
    );
    assert(
      !_canPerformAction(SemanticsAction.decrease) || (_value == '') == (_decreasedValue == ''),
      'A SemanticsNode with action "increase" needs to be annotated with either both "value" and "decreasedValue" or neither',
    );
  }


  /// Returns a summary of the semantics for this node.
  ///
  /// If this node has [mergeAllDescendantsIntoThisNode], then the returned data
  /// includes the information from this node's descendants. Otherwise, the
  /// returned data matches the data on this node.
  SemanticsData getSemanticsData() {
    int flags = _flags;
    int actions = _actionsAsBits;
    String label = _label;
    String hint = _hint;
    String value = _value;
    String increasedValue = _increasedValue;
    String decreasedValue = _decreasedValue;
    TextDirection textDirection = _textDirection;
    Set<SemanticsTag> mergedTags = tags == null ? null : Set<SemanticsTag>.from(tags);
    TextSelection textSelection = _textSelection;
    int scrollChildCount = _scrollChildCount;
    int scrollIndex = _scrollIndex;
    double scrollPosition = _scrollPosition;
    double scrollExtentMax = _scrollExtentMax;
    double scrollExtentMin = _scrollExtentMin;
    int platformViewId = _platformViewId;
    int maxValueLength = _maxValueLength;
    int currentValueLength = _currentValueLength;
    final double elevation = _elevation;
    double thickness = _thickness;
    final Set<int> customSemanticsActionIds = <int>{};
    for (final CustomSemanticsAction action in _customSemanticsActions.keys)
      customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
    if (hintOverrides != null) {
      if (hintOverrides.onTapHint != null) {
        final CustomSemanticsAction action = CustomSemanticsAction.overridingAction(
          hint: hintOverrides.onTapHint,
          action: SemanticsAction.tap,
        );
        customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
      }
      if (hintOverrides.onLongPressHint != null) {
        final CustomSemanticsAction action = CustomSemanticsAction.overridingAction(
          hint: hintOverrides.onLongPressHint,
          action: SemanticsAction.longPress,
        );
        customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
      }
    }

    if (mergeAllDescendantsIntoThisNode) {
      _visitDescendants((SemanticsNode node) {
        assert(node.isMergedIntoParent);
        flags |= node._flags;
        actions |= node._actionsAsBits;
        textDirection ??= node._textDirection;
        textSelection ??= node._textSelection;
        scrollChildCount ??= node._scrollChildCount;
        scrollIndex ??= node._scrollIndex;
        scrollPosition ??= node._scrollPosition;
        scrollExtentMax ??= node._scrollExtentMax;
        scrollExtentMin ??= node._scrollExtentMin;
        platformViewId ??= node._platformViewId;
        maxValueLength ??= node._maxValueLength;
        currentValueLength ??= node._currentValueLength;
        if (value == '' || value == null)
          value = node._value;
        if (increasedValue == '' || increasedValue == null)
          increasedValue = node._increasedValue;
        if (decreasedValue == '' || decreasedValue == null)
          decreasedValue = node._decreasedValue;
        if (node.tags != null) {
          mergedTags ??= <SemanticsTag>{};
          mergedTags.addAll(node.tags);
        }
        if (node._customSemanticsActions != null) {
          for (final CustomSemanticsAction action in _customSemanticsActions.keys)
            customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
        }
        if (node.hintOverrides != null) {
          if (node.hintOverrides.onTapHint != null) {
            final CustomSemanticsAction action = CustomSemanticsAction.overridingAction(
              hint: node.hintOverrides.onTapHint,
              action: SemanticsAction.tap,
            );
            customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
          }
          if (node.hintOverrides.onLongPressHint != null) {
            final CustomSemanticsAction action = CustomSemanticsAction.overridingAction(
              hint: node.hintOverrides.onLongPressHint,
              action: SemanticsAction.longPress,
            );
            customSemanticsActionIds.add(CustomSemanticsAction.getIdentifier(action));
          }
        }
        label = _concatStrings(
          thisString: label,
          thisTextDirection: textDirection,
          otherString: node._label,
          otherTextDirection: node._textDirection,
        );
        hint = _concatStrings(
          thisString: hint,
          thisTextDirection: textDirection,
          otherString: node._hint,
          otherTextDirection: node._textDirection,
        );

        thickness = math.max(thickness, node._thickness + node._elevation);

        return true;
      });
    }

    return SemanticsData(
      flags: flags,
      actions: actions,
      label: label,
      value: value,
      increasedValue: increasedValue,
      decreasedValue: decreasedValue,
      hint: hint,
      textDirection: textDirection,
      rect: rect,
      transform: transform,
      elevation: elevation,
      thickness: thickness,
      tags: mergedTags,
      textSelection: textSelection,
      scrollChildCount: scrollChildCount,
      scrollIndex: scrollIndex,
      scrollPosition: scrollPosition,
      scrollExtentMax: scrollExtentMax,
      scrollExtentMin: scrollExtentMin,
      platformViewId: platformViewId,
      maxValueLength: maxValueLength,
      currentValueLength: currentValueLength,
      customSemanticsActionIds: customSemanticsActionIds.toList()..sort(),
    );
  }

  static Float64List _initIdentityTransform() {
    return Matrix4.identity().storage;
  }

  static final Int32List _kEmptyChildList = Int32List(0);
  static final Int32List _kEmptyCustomSemanticsActionsList = Int32List(0);
  static final Float64List _kIdentityTransform = _initIdentityTransform();

  void _addToUpdate(ui.SemanticsUpdateBuilder builder, Set<int> customSemanticsActionIdsUpdate) {
    assert(_dirty);
    final SemanticsData data = getSemanticsData();
    Int32List childrenInTraversalOrder;
    Int32List childrenInHitTestOrder;
    if (!hasChildren || mergeAllDescendantsIntoThisNode) {
      childrenInTraversalOrder = _kEmptyChildList;
      childrenInHitTestOrder = _kEmptyChildList;
    } else {
      final int childCount = _children.length;
      final List<SemanticsNode> sortedChildren = _childrenInTraversalOrder();
      childrenInTraversalOrder = Int32List(childCount);
      for (int i = 0; i < childCount; i += 1) {
        childrenInTraversalOrder[i] = sortedChildren[i].id;
      }
      // _children is sorted in paint order, so we invert it to get the hit test
      // order.
      childrenInHitTestOrder = Int32List(childCount);
      for (int i = childCount - 1; i >= 0; i -= 1) {
        childrenInHitTestOrder[i] = _children[childCount - i - 1].id;
      }
    }
    Int32List customSemanticsActionIds;
    if (data.customSemanticsActionIds?.isNotEmpty == true) {
      customSemanticsActionIds = Int32List(data.customSemanticsActionIds.length);
      for (int i = 0; i < data.customSemanticsActionIds.length; i++) {
        customSemanticsActionIds[i] = data.customSemanticsActionIds[i];
        customSemanticsActionIdsUpdate.add(data.customSemanticsActionIds[i]);
      }
    }
    builder.updateNode(
      id: id,
      flags: data.flags,
      actions: data.actions,
      rect: data.rect,
      label: data.label,
      value: data.value,
      decreasedValue: data.decreasedValue,
      increasedValue: data.increasedValue,
      hint: data.hint,
      textDirection: data.textDirection,
      textSelectionBase: data.textSelection != null ? data.textSelection.baseOffset : -1,
      textSelectionExtent: data.textSelection != null ? data.textSelection.extentOffset : -1,
      platformViewId: data.platformViewId ?? -1,
      maxValueLength: data.maxValueLength ?? -1,
      currentValueLength: data.currentValueLength ?? -1,
      scrollChildren: data.scrollChildCount ?? 0,
      scrollIndex: data.scrollIndex ?? 0 ,
      scrollPosition: data.scrollPosition ?? double.nan,
      scrollExtentMax: data.scrollExtentMax ?? double.nan,
      scrollExtentMin: data.scrollExtentMin ?? double.nan,
      transform: data.transform?.storage ?? _kIdentityTransform,
      elevation: data.elevation,
      thickness: data.thickness,
      childrenInTraversalOrder: childrenInTraversalOrder,
      childrenInHitTestOrder: childrenInHitTestOrder,
      additionalActions: customSemanticsActionIds ?? _kEmptyCustomSemanticsActionsList,
    );
    _dirty = false;
  }

  /// Builds a new list made of [_children] sorted in semantic traversal order.
  List<SemanticsNode> _childrenInTraversalOrder() {
    TextDirection inheritedTextDirection = textDirection;
    SemanticsNode ancestor = parent;
    while (inheritedTextDirection == null && ancestor != null) {
      inheritedTextDirection = ancestor.textDirection;
      ancestor = ancestor.parent;
    }

    List<SemanticsNode> childrenInDefaultOrder;
    if (inheritedTextDirection != null) {
      childrenInDefaultOrder = _childrenInDefaultOrder(_children, inheritedTextDirection);
    } else {
      // In the absence of text direction default to paint order.
      childrenInDefaultOrder = _children;
    }

    // List.sort does not guarantee stable sort order. Therefore, children are
    // first partitioned into groups that have compatible sort keys, i.e. keys
    // in the same group can be compared to each other. These groups stay in
    // the same place. Only children within the same group are sorted.
    final List<_TraversalSortNode> everythingSorted = <_TraversalSortNode>[];
    final List<_TraversalSortNode> sortNodes = <_TraversalSortNode>[];
    SemanticsSortKey lastSortKey;
    for (int position = 0; position < childrenInDefaultOrder.length; position += 1) {
      final SemanticsNode child = childrenInDefaultOrder[position];
      final SemanticsSortKey sortKey = child.sortKey;
      lastSortKey = position > 0
          ? childrenInDefaultOrder[position - 1].sortKey
          : null;
      final bool isCompatibleWithPreviousSortKey = position == 0 ||
          sortKey.runtimeType == lastSortKey.runtimeType &&
          (sortKey == null || sortKey.name == lastSortKey.name);
      if (!isCompatibleWithPreviousSortKey && sortNodes.isNotEmpty) {
        // Do not sort groups with null sort keys. List.sort does not guarantee
        // a stable sort order.
        if (lastSortKey != null) {
          sortNodes.sort();
        }
        everythingSorted.addAll(sortNodes);
        sortNodes.clear();
      }

      sortNodes.add(_TraversalSortNode(
        node: child,
        sortKey: sortKey,
        position: position,
      ));
    }

    // Do not sort groups with null sort keys. List.sort does not guarantee
    // a stable sort order.
    if (lastSortKey != null) {
      sortNodes.sort();
    }
    everythingSorted.addAll(sortNodes);

    return everythingSorted
      .map<SemanticsNode>((_TraversalSortNode sortNode) => sortNode.node)
      .toList();
  }

  /// Sends a [SemanticsEvent] associated with this [SemanticsNode].
  ///
  /// Semantics events should be sent to inform interested parties (like
  /// the accessibility system of the operating system) about changes to the UI.
  ///
  /// For example, if this semantics node represents a scrollable list, a
  /// [ScrollCompletedSemanticsEvent] should be sent after a scroll action is completed.
  /// That way, the operating system can give additional feedback to the user
  /// about the state of the UI (e.g. on Android a ping sound is played to
  /// indicate a successful scroll in accessibility mode).
  void sendEvent(SemanticsEvent event) {
    if (!attached)
      return;
    SystemChannels.accessibility.send(event.toMap(nodeId: id));
  }

  @override
  String toStringShort() => '${objectRuntimeType(this, 'SemanticsNode')}#$id';

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    bool hideOwner = true;
    if (_dirty) {
      final bool inDirtyNodes = owner != null && owner._dirtyNodes.contains(this);
      properties.add(FlagProperty('inDirtyNodes', value: inDirtyNodes, ifTrue: 'dirty', ifFalse: 'STALE'));
      hideOwner = inDirtyNodes;
    }
    properties.add(DiagnosticsProperty<SemanticsOwner>('owner', owner, level: hideOwner ? DiagnosticLevel.hidden : DiagnosticLevel.info));
    properties.add(FlagProperty('isMergedIntoParent', value: isMergedIntoParent, ifTrue: 'merged up ⬆️'));
    properties.add(FlagProperty('mergeAllDescendantsIntoThisNode', value: mergeAllDescendantsIntoThisNode, ifTrue: 'merge boundary ⛔️'));
    final Offset offset = transform != null ? MatrixUtils.getAsTranslation(transform) : null;
    if (offset != null) {
      properties.add(DiagnosticsProperty<Rect>('rect', rect.shift(offset), showName: false));
    } else {
      final double scale = transform != null ? MatrixUtils.getAsScale(transform) : null;
      String description;
      if (scale != null) {
        description = '$rect scaled by ${scale.toStringAsFixed(1)}x';
      } else if (transform != null && !MatrixUtils.isIdentity(transform)) {
        final String matrix = transform.toString().split('\n').take(4).map<String>((String line) => line.substring(4)).join('; ');
        description = '$rect with transform [$matrix]';
      }
      properties.add(DiagnosticsProperty<Rect>('rect', rect, description: description, showName: false));
    }
    properties.add(IterableProperty<String>('tags', tags?.map((SemanticsTag tag) => tag.name), defaultValue: null));
    final List<String> actions = _actions.keys.map<String>((SemanticsAction action) => describeEnum(action)).toList()..sort();
    final List<String> customSemanticsActions = _customSemanticsActions.keys
      .map<String>((CustomSemanticsAction action) => action.label)
      .toList();
    properties.add(IterableProperty<String>('actions', actions, ifEmpty: null));
    properties.add(IterableProperty<String>('customActions', customSemanticsActions, ifEmpty: null));
    final List<String> flags = SemanticsFlag.values.values.where((SemanticsFlag flag) => hasFlag(flag)).map((SemanticsFlag flag) => flag.toString().substring('SemanticsFlag.'.length)).toList();
    properties.add(IterableProperty<String>('flags', flags, ifEmpty: null));
    properties.add(FlagProperty('isInvisible', value: isInvisible, ifTrue: 'invisible'));
    properties.add(FlagProperty('isHidden', value: hasFlag(SemanticsFlag.isHidden), ifTrue: 'HIDDEN'));
    properties.add(StringProperty('label', _label, defaultValue: ''));
    properties.add(StringProperty('value', _value, defaultValue: ''));
    properties.add(StringProperty('increasedValue', _increasedValue, defaultValue: ''));
    properties.add(StringProperty('decreasedValue', _decreasedValue, defaultValue: ''));
    properties.add(StringProperty('hint', _hint, defaultValue: ''));
    properties.add(EnumProperty<TextDirection>('textDirection', _textDirection, defaultValue: null));
    properties.add(DiagnosticsProperty<SemanticsSortKey>('sortKey', sortKey, defaultValue: null));
    if (_textSelection?.isValid == true)
      properties.add(MessageProperty('text selection', '[${_textSelection.start}, ${_textSelection.end}]'));
    properties.add(IntProperty('platformViewId', platformViewId, defaultValue: null));
    properties.add(IntProperty('maxValueLength', maxValueLength, defaultValue: null));
    properties.add(IntProperty('currentValueLength', currentValueLength, defaultValue: null));
    properties.add(IntProperty('scrollChildren', scrollChildCount, defaultValue: null));
    properties.add(IntProperty('scrollIndex', scrollIndex, defaultValue: null));
    properties.add(DoubleProperty('scrollExtentMin', scrollExtentMin, defaultValue: null));
    properties.add(DoubleProperty('scrollPosition', scrollPosition, defaultValue: null));
    properties.add(DoubleProperty('scrollExtentMax', scrollExtentMax, defaultValue: null));
    properties.add(DoubleProperty('elevation', elevation, defaultValue: 0.0));
    properties.add(DoubleProperty('thickness', thickness, defaultValue: 0.0));
  }

  /// Returns a string representation of this node and its descendants.
  ///
  /// The order in which the children of the [SemanticsNode] will be printed is
  /// controlled by the [childOrder] parameter.
  @override
  String toStringDeep({
    String prefixLineOne = '',
    String prefixOtherLines,
    DiagnosticLevel minLevel = DiagnosticLevel.debug,
    DebugSemanticsDumpOrder childOrder = DebugSemanticsDumpOrder.traversalOrder,
  }) {
    assert(childOrder != null);
    return toDiagnosticsNode(childOrder: childOrder).toStringDeep(prefixLineOne: prefixLineOne, prefixOtherLines: prefixOtherLines, minLevel: minLevel);
  }

  @override
  DiagnosticsNode toDiagnosticsNode({
    String name,
    DiagnosticsTreeStyle style = DiagnosticsTreeStyle.sparse,
    DebugSemanticsDumpOrder childOrder = DebugSemanticsDumpOrder.traversalOrder,
  }) {
    return _SemanticsDiagnosticableNode(
      name: name,
      value: this,
      style: style,
      childOrder: childOrder,
    );
  }

  @override
  List<DiagnosticsNode> debugDescribeChildren({ DebugSemanticsDumpOrder childOrder = DebugSemanticsDumpOrder.inverseHitTest }) {
    return debugListChildrenInOrder(childOrder)
      .map<DiagnosticsNode>((SemanticsNode node) => node.toDiagnosticsNode(childOrder: childOrder))
      .toList();
  }

  /// Returns the list of direct children of this node in the specified order.
  List<SemanticsNode> debugListChildrenInOrder(DebugSemanticsDumpOrder childOrder) {
    assert(childOrder != null);
    if (_children == null)
      return const <SemanticsNode>[];

    switch (childOrder) {
      case DebugSemanticsDumpOrder.inverseHitTest:
        return _children;
      case DebugSemanticsDumpOrder.traversalOrder:
        return _childrenInTraversalOrder();
    }
    assert(false);
    return null;
  }
}

/// An edge of a box, such as top, bottom, left or right, used to compute
/// [SemanticsNode]s that overlap vertically or horizontally.
///
/// For computing horizontal overlap in an LTR setting we create two [_BoxEdge]
/// objects for each [SemanticsNode]: one representing the left edge (marked
/// with [isLeadingEdge] equal to true) and one for the right edge (with [isLeadingEdge]
/// equal to false). Similarly, for vertical overlap we also create two objects
/// for each [SemanticsNode], one for the top and one for the bottom edge.
class _BoxEdge implements Comparable<_BoxEdge> {
  _BoxEdge({
    @required this.isLeadingEdge,
    @required this.offset,
    @required this.node,
  }) : assert(isLeadingEdge != null),
       assert(offset != null),
       assert(offset.isFinite),
       assert(node != null);

  /// True if the edge comes before the seconds edge along the traversal
  /// direction, and false otherwise.
  ///
  /// This field is never null.
  ///
  /// For example, in LTR traversal the left edge's [isLeadingEdge] is set to true,
  /// the right edge's [isLeadingEdge] is set to false. When considering vertical
  /// ordering of boxes, the top edge is the start edge, and the bottom edge is
  /// the end edge.
  final bool isLeadingEdge;

  /// The offset from the start edge of the parent [SemanticsNode] in the
  /// direction of the traversal.
  final double offset;

  /// The node whom this edge belongs.
  final SemanticsNode node;

  @override
  int compareTo(_BoxEdge other) {
    return (offset - other.offset).sign.toInt();
  }
}

/// A group of [nodes] that are disjoint vertically or horizontally from other
/// nodes that share the same [SemanticsNode] parent.
///
/// The [nodes] are sorted among each other separately from other nodes.
class _SemanticsSortGroup extends Comparable<_SemanticsSortGroup> {
  _SemanticsSortGroup({
    @required this.startOffset,
    @required this.textDirection,
  }) : assert(startOffset != null);

  /// The offset from the start edge of the parent [SemanticsNode] in the
  /// direction of the traversal.
  ///
  /// This value is equal to the [_BoxEdge.offset] of the first node in the
  /// [nodes] list being considered.
  final double startOffset;

  final TextDirection textDirection;

  /// The nodes that are sorted among each other.
  final List<SemanticsNode> nodes = <SemanticsNode>[];

  @override
  int compareTo(_SemanticsSortGroup other) {
    return (startOffset - other.startOffset).sign.toInt();
  }

  /// Sorts this group assuming that [nodes] belong to the same vertical group.
  ///
  /// This method breaks up this group into horizontal [_SemanticsSortGroup]s
  /// then sorts them using [sortedWithinKnot].
  List<SemanticsNode> sortedWithinVerticalGroup() {
    final List<_BoxEdge> edges = <_BoxEdge>[];
    for (final SemanticsNode child in nodes) {
      // Using a small delta to shrink child rects removes overlapping cases.
      final Rect childRect = child.rect.deflate(0.1);
      edges.add(_BoxEdge(
        isLeadingEdge: true,
        offset: _pointInParentCoordinates(child, childRect.topLeft).dx,
        node: child,
      ));
      edges.add(_BoxEdge(
        isLeadingEdge: false,
        offset: _pointInParentCoordinates(child, childRect.bottomRight).dx,
        node: child,
      ));
    }
    edges.sort();

    List<_SemanticsSortGroup> horizontalGroups = <_SemanticsSortGroup>[];
    _SemanticsSortGroup group;
    int depth = 0;
    for (final _BoxEdge edge in edges) {
      if (edge.isLeadingEdge) {
        depth += 1;
        group ??= _SemanticsSortGroup(
          startOffset: edge.offset,
          textDirection: textDirection,
        );
        group.nodes.add(edge.node);
      } else {
        depth -= 1;
      }
      if (depth == 0) {
        horizontalGroups.add(group);
        group = null;
      }
    }
    horizontalGroups.sort();

    if (textDirection == TextDirection.rtl) {
      horizontalGroups = horizontalGroups.reversed.toList();
    }

    return horizontalGroups
      .expand((_SemanticsSortGroup group) => group.sortedWithinKnot())
      .toList();
  }

  /// Sorts [nodes] where nodes intersect both vertically and horizontally.
  ///
  /// In the special case when [nodes] contains one or less nodes, this method
  /// returns [nodes] unchanged.
  ///
  /// This method constructs a graph, where vertices are [SemanticsNode]s and
  /// edges are "traversed before" relation between pairs of nodes. The sort
  /// order is the topological sorting of the graph, with the original order of
  /// [nodes] used as the tie breaker.
  ///
  /// Whether a node is traversed before another node is determined by the
  /// vector that connects the two nodes' centers. If the vector "points to the
  /// right or down", defined as the [Offset.direction] being between `-pi/4`
  /// and `3*pi/4`), then the semantics node whose center is at the end of the
  /// vector is said to be traversed after.
  List<SemanticsNode> sortedWithinKnot() {
    if (nodes.length <= 1) {
      // Trivial knot. Nothing to do.
      return nodes;
    }
    final Map<int, SemanticsNode> nodeMap = <int, SemanticsNode>{};
    final Map<int, int> edges = <int, int>{};
    for (final SemanticsNode node in nodes) {
      nodeMap[node.id] = node;
      final Offset center = _pointInParentCoordinates(node, node.rect.center);
      for (final SemanticsNode nextNode in nodes) {
        if (identical(node, nextNode) || edges[nextNode.id] == node.id) {
          // Skip self or when we've already established that the next node
          // points to current node.
          continue;
        }

        final Offset nextCenter = _pointInParentCoordinates(nextNode, nextNode.rect.center);
        final Offset centerDelta = nextCenter - center;
        // When centers coincide, direction is 0.0.
        final double direction = centerDelta.direction;
        final bool isLtrAndForward = textDirection == TextDirection.ltr &&
            -math.pi / 4 < direction && direction < 3 * math.pi / 4;
        final bool isRtlAndForward = textDirection == TextDirection.rtl &&
            (direction < -3 * math.pi / 4 || direction > 3 * math.pi / 4);
        if (isLtrAndForward || isRtlAndForward) {
          edges[node.id] = nextNode.id;
        }
      }
    }

    final List<int> sortedIds = <int>[];
    final Set<int> visitedIds = <int>{};
    final List<SemanticsNode> startNodes = nodes.toList()..sort((SemanticsNode a, SemanticsNode b) {
      final Offset aTopLeft = _pointInParentCoordinates(a, a.rect.topLeft);
      final Offset bTopLeft = _pointInParentCoordinates(b, b.rect.topLeft);
      final int verticalDiff = aTopLeft.dy.compareTo(bTopLeft.dy);
      if (verticalDiff != 0) {
        return -verticalDiff;
      }
      return -aTopLeft.dx.compareTo(bTopLeft.dx);
    });

    void search(int id) {
      if (visitedIds.contains(id)) {
        return;
      }
      visitedIds.add(id);
      if (edges.containsKey(id)) {
        search(edges[id]);
      }
      sortedIds.add(id);
    }

    startNodes.map<int>((SemanticsNode node) => node.id).forEach(search);
    return sortedIds.map<SemanticsNode>((int id) => nodeMap[id]).toList().reversed.toList();
  }
}

/// Converts `point` to the `node`'s parent's coordinate system.
Offset _pointInParentCoordinates(SemanticsNode node, Offset point) {
  if (node.transform == null) {
    return point;
  }
  final Vector3 vector = Vector3(point.dx, point.dy, 0.0);
  node.transform.transform3(vector);
  return Offset(vector.x, vector.y);
}

/// Sorts `children` using the default sorting algorithm, and returns them as a
/// new list.
///
/// The algorithm first breaks up children into groups such that no two nodes
/// from different groups overlap vertically. These groups are sorted vertically
/// according to their [_SemanticsSortGroup.startOffset].
///
/// Within each group, the nodes are sorted using
/// [_SemanticsSortGroup.sortedWithinVerticalGroup].
///
/// For an illustration of the algorithm see http://bit.ly/flutter-default-traversal.
List<SemanticsNode> _childrenInDefaultOrder(List<SemanticsNode> children, TextDirection textDirection) {
  final List<_BoxEdge> edges = <_BoxEdge>[];
  for (final SemanticsNode child in children) {
    assert(child.rect.isFinite);
    // Using a small delta to shrink child rects removes overlapping cases.
    final Rect childRect = child.rect.deflate(0.1);
    edges.add(_BoxEdge(
      isLeadingEdge: true,
      offset: _pointInParentCoordinates(child, childRect.topLeft).dy,
      node: child,
    ));
    edges.add(_BoxEdge(
      isLeadingEdge: false,
      offset: _pointInParentCoordinates(child, childRect.bottomRight).dy,
      node: child,
    ));
  }
  edges.sort();

  final List<_SemanticsSortGroup> verticalGroups = <_SemanticsSortGroup>[];
  _SemanticsSortGroup group;
  int depth = 0;
  for (final _BoxEdge edge in edges) {
    if (edge.isLeadingEdge) {
      depth += 1;
      group ??= _SemanticsSortGroup(
        startOffset: edge.offset,
        textDirection: textDirection,
      );
      group.nodes.add(edge.node);
    } else {
      depth -= 1;
    }
    if (depth == 0) {
      verticalGroups.add(group);
      group = null;
    }
  }
  verticalGroups.sort();

  return verticalGroups
    .expand((_SemanticsSortGroup group) => group.sortedWithinVerticalGroup())
    .toList();
}

/// The implementation of [Comparable] that implements the ordering of
/// [SemanticsNode]s in the accessibility traversal.
///
/// [SemanticsNode]s are sorted prior to sending them to the engine side.
///
/// This implementation considers a [node]'s [sortKey] and its position within
/// the list of its siblings. [sortKey] takes precedence over position.
class _TraversalSortNode implements Comparable<_TraversalSortNode> {
  _TraversalSortNode({
    @required this.node,
    this.sortKey,
    @required this.position,
  })
    : assert(node != null),
      assert(position != null);

  /// The node whose position this sort node determines.
  final SemanticsNode node;

  /// Determines the position of this node among its siblings.
  ///
  /// Sort keys take precedence over other attributes, such as
  /// [position].
  final SemanticsSortKey sortKey;

  /// Position within the list of siblings as determined by the default sort
  /// order.
  final int position;

  @override
  int compareTo(_TraversalSortNode other) {
    if (sortKey == null || other?.sortKey == null) {
      return position - other.position;
    }
    return sortKey.compareTo(other.sortKey);
  }
}

/// Owns [SemanticsNode] objects and notifies listeners of changes to the
/// render tree semantics.
///
/// To listen for semantic updates, call [PipelineOwner.ensureSemantics] to
/// obtain a [SemanticsHandle]. This will create a [SemanticsOwner] if
/// necessary.
class SemanticsOwner extends ChangeNotifier {
  final Set<SemanticsNode> _dirtyNodes = <SemanticsNode>{};
  final Map<int, SemanticsNode> _nodes = <int, SemanticsNode>{};
  final Set<SemanticsNode> _detachedNodes = <SemanticsNode>{};

  /// The root node of the semantics tree, if any.
  ///
  /// If the semantics tree is empty, returns null.
  SemanticsNode get rootSemanticsNode => _nodes[0];

  @override
  void dispose() {
    _dirtyNodes.clear();
    _nodes.clear();
    _detachedNodes.clear();
    super.dispose();
  }

  /// Update the semantics using [Window.updateSemantics].
  void sendSemanticsUpdate() {
    if (_dirtyNodes.isEmpty)
      return;
    final Set<int> customSemanticsActionIds = <int>{};
    final List<SemanticsNode> visitedNodes = <SemanticsNode>[];
    while (_dirtyNodes.isNotEmpty) {
      final List<SemanticsNode> localDirtyNodes = _dirtyNodes.where((SemanticsNode node) => !_detachedNodes.contains(node)).toList();
      _dirtyNodes.clear();
      _detachedNodes.clear();
      localDirtyNodes.sort((SemanticsNode a, SemanticsNode b) => a.depth - b.depth);
      visitedNodes.addAll(localDirtyNodes);
      for (final SemanticsNode node in localDirtyNodes) {
        assert(node._dirty);
        assert(node.parent == null || !node.parent.isPartOfNodeMerging || node.isMergedIntoParent);
        if (node.isPartOfNodeMerging) {
          assert(node.mergeAllDescendantsIntoThisNode || node.parent != null);
          // if we're merged into our parent, make sure our parent is added to the dirty list
          if (node.parent != null && node.parent.isPartOfNodeMerging)
            node.parent._markDirty(); // this can add the node to the dirty list
        }
      }
    }
    visitedNodes.sort((SemanticsNode a, SemanticsNode b) => a.depth - b.depth);
    final ui.SemanticsUpdateBuilder builder = ui.SemanticsUpdateBuilder();
    for (final SemanticsNode node in visitedNodes) {
      assert(node.parent?._dirty != true); // could be null (no parent) or false (not dirty)
      // The _serialize() method marks the node as not dirty, and
      // recurses through the tree to do a deep serialization of all
      // contiguous dirty nodes. This means that when we return here,
      // it's quite possible that subsequent nodes are no longer
      // dirty. We skip these here.
      // We also skip any nodes that were reset and subsequently
      // dropped entirely (RenderObject.markNeedsSemanticsUpdate()
      // calls reset() on its SemanticsNode if onlyChanges isn't set,
      // which happens e.g. when the node is no longer contributing
      // semantics).
      if (node._dirty && node.attached)
        node._addToUpdate(builder, customSemanticsActionIds);
    }
    _dirtyNodes.clear();
    for (final int actionId in customSemanticsActionIds) {
      final CustomSemanticsAction action = CustomSemanticsAction.getAction(actionId);
      builder.updateCustomAction(id: actionId, label: action.label, hint: action.hint, overrideId: action.action?.index ?? -1);
    }
    SemanticsBinding.instance.window.updateSemantics(builder.build());
    notifyListeners();
  }

  _SemanticsActionHandler _getSemanticsActionHandlerForId(int id, SemanticsAction action) {
    SemanticsNode result = _nodes[id];
    if (result != null && result.isPartOfNodeMerging && !result._canPerformAction(action)) {
      result._visitDescendants((SemanticsNode node) {
        if (node._canPerformAction(action)) {
          result = node;
          return false; // found node, abort walk
        }
        return true; // continue walk
      });
    }
    if (result == null || !result._canPerformAction(action))
      return null;
    return result._actions[action];
  }

  /// Asks the [SemanticsNode] with the given id to perform the given action.
  ///
  /// If the [SemanticsNode] has not indicated that it can perform the action,
  /// this function does nothing.
  ///
  /// If the given `action` requires arguments they need to be passed in via
  /// the `args` parameter.
  void performAction(int id, SemanticsAction action, [ dynamic args ]) {
    assert(action != null);
    final _SemanticsActionHandler handler = _getSemanticsActionHandlerForId(id, action);
    if (handler != null) {
      handler(args);
      return;
    }

    // Default actions if no [handler] was provided.
    if (action == SemanticsAction.showOnScreen && _nodes[id]._showOnScreen != null)
      _nodes[id]._showOnScreen();
  }

  _SemanticsActionHandler _getSemanticsActionHandlerForPosition(SemanticsNode node, Offset position, SemanticsAction action) {
    if (node.transform != null) {
      final Matrix4 inverse = Matrix4.identity();
      if (inverse.copyInverse(node.transform) == 0.0)
        return null;
      position = MatrixUtils.transformPoint(inverse, position);
    }
    if (!node.rect.contains(position))
      return null;
    if (node.mergeAllDescendantsIntoThisNode) {
      SemanticsNode result;
      node._visitDescendants((SemanticsNode child) {
        if (child._canPerformAction(action)) {
          result = child;
          return false;
        }
        return true;
      });
      return result?._actions[action];
    }
    if (node.hasChildren) {
      for (final SemanticsNode child in node._children.reversed) {
        final _SemanticsActionHandler handler = _getSemanticsActionHandlerForPosition(child, position, action);
        if (handler != null)
          return handler;
      }
    }
    return node._actions[action];
  }

  /// Asks the [SemanticsNode] at the given position to perform the given action.
  ///
  /// If the [SemanticsNode] has not indicated that it can perform the action,
  /// this function does nothing.
  ///
  /// If the given `action` requires arguments they need to be passed in via
  /// the `args` parameter.
  void performActionAt(Offset position, SemanticsAction action, [ dynamic args ]) {
    assert(action != null);
    final SemanticsNode node = rootSemanticsNode;
    if (node == null)
      return;
    final _SemanticsActionHandler handler = _getSemanticsActionHandlerForPosition(node, position, action);
    if (handler != null)
      handler(args);
  }

  @override
  String toString() => describeIdentity(this);
}

/// Describes the semantic information associated with the owning
/// [RenderObject].
///
/// The information provided in the configuration is used to generate the
/// semantics tree.
class SemanticsConfiguration {

  // SEMANTIC BOUNDARY BEHAVIOR

  /// Whether the [RenderObject] owner of this configuration wants to own its
  /// own [SemanticsNode].
  ///
  /// When set to true semantic information associated with the [RenderObject]
  /// owner of this configuration or any of its descendants will not leak into
  /// parents. The [SemanticsNode] generated out of this configuration will
  /// act as a boundary.
  ///
  /// Whether descendants of the owning [RenderObject] can add their semantic
  /// information to the [SemanticsNode] introduced by this configuration
  /// is controlled by [explicitChildNodes].
  ///
  /// This has to be true if [isMergingDescendantsIntoOneNode] is also true.
  bool get isSemanticBoundary => _isSemanticBoundary;
  bool _isSemanticBoundary = false;
  set isSemanticBoundary(bool value) {
    assert(!isMergingSemanticsOfDescendants || value);
    _isSemanticBoundary = value;
  }

  /// Whether the configuration forces all children of the owning [RenderObject]
  /// that want to contribute semantic information to the semantics tree to do
  /// so in the form of explicit [SemanticsNode]s.
  ///
  /// When set to false children of the owning [RenderObject] are allowed to
  /// annotate [SemanticsNode]s of their parent with the semantic information
  /// they want to contribute to the semantic tree.
  /// When set to true the only way for children of the owning [RenderObject]
  /// to contribute semantic information to the semantic tree is to introduce
  /// new explicit [SemanticsNode]s to the tree.
  ///
  /// This setting is often used in combination with [isSemanticBoundary] to
  /// create semantic boundaries that are either writable or not for children.
  bool explicitChildNodes = false;

  /// Whether the owning [RenderObject] makes other [RenderObject]s previously
  /// painted within the same semantic boundary unreachable for accessibility
  /// purposes.
  ///
  /// If set to true, the semantic information for all siblings and cousins of
  /// this node, that are earlier in a depth-first pre-order traversal, are
  /// dropped from the semantics tree up until a semantic boundary (as defined
  /// by [isSemanticBoundary]) is reached.
  ///
  /// If [isSemanticBoundary] and [isBlockingSemanticsOfPreviouslyPaintedNodes]
  /// is set on the same node, all previously painted siblings and cousins up
  /// until the next ancestor that is a semantic boundary are dropped.
  ///
  /// Paint order as established by [RenderObject.visitChildrenForSemantics] is
  /// used to determine if a node is previous to this one.
  bool isBlockingSemanticsOfPreviouslyPaintedNodes = false;

  // SEMANTIC ANNOTATIONS
  // These will end up on [SemanticsNode]s generated from
  // [SemanticsConfiguration]s.

  /// Whether this configuration is empty.
  ///
  /// An empty configuration doesn't contain any semantic information that it
  /// wants to contribute to the semantics tree.
  bool get hasBeenAnnotated => _hasBeenAnnotated;
  bool _hasBeenAnnotated = false;

  /// The actions (with associated action handlers) that this configuration
  /// would like to contribute to the semantics tree.
  ///
  /// See also:
  ///
  ///  * [addAction] to add an action.
  final Map<SemanticsAction, _SemanticsActionHandler> _actions = <SemanticsAction, _SemanticsActionHandler>{};

  int _actionsAsBits = 0;

  /// Adds an `action` to the semantics tree.
  ///
  /// The provided `handler` is called to respond to the user triggered
  /// `action`.
  void _addAction(SemanticsAction action, _SemanticsActionHandler handler) {
    assert(handler != null);
    _actions[action] = handler;
    _actionsAsBits |= action.index;
    _hasBeenAnnotated = true;
  }

  /// Adds an `action` to the semantics tree, whose `handler` does not expect
  /// any arguments.
  ///
  /// The provided `handler` is called to respond to the user triggered
  /// `action`.
  void _addArgumentlessAction(SemanticsAction action, VoidCallback handler) {
    assert(handler != null);
    _addAction(action, (dynamic args) {
      assert(args == null);
      handler();
    });
  }

  /// The handler for [SemanticsAction.tap].
  ///
  /// This is the semantic equivalent of a user briefly tapping the screen with
  /// the finger without moving it. For example, a button should implement this
  /// action.
  ///
  /// VoiceOver users on iOS and TalkBack users on Android can trigger this
  /// action by double-tapping the screen while an element is focused.
  ///
  /// On Android prior to Android Oreo a double-tap on the screen while an
  /// element with an [onTap] handler is focused will not call the registered
  /// handler. Instead, Android will simulate a pointer down and up event at the
  /// center of the focused element. Those pointer events will get dispatched
  /// just like a regular tap with TalkBack disabled would: The events will get
  /// processed by any [GestureDetector] listening for gestures in the center of
  /// the focused element. Therefore, to ensure that [onTap] handlers work
  /// properly on Android versions prior to Oreo, a [GestureDetector] with an
  /// onTap handler should always be wrapping an element that defines a
  /// semantic [onTap] handler. By default a [GestureDetector] will register its
  /// own semantic [onTap] handler that follows this principle.
  VoidCallback get onTap => _onTap;
  VoidCallback _onTap;
  set onTap(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.tap, value);
    _onTap = value;
  }

  /// The handler for [SemanticsAction.longPress].
  ///
  /// This is the semantic equivalent of a user pressing and holding the screen
  /// with the finger for a few seconds without moving it.
  ///
  /// VoiceOver users on iOS and TalkBack users on Android can trigger this
  /// action by double-tapping the screen without lifting the finger after the
  /// second tap.
  VoidCallback get onLongPress => _onLongPress;
  VoidCallback _onLongPress;
  set onLongPress(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.longPress, value);
    _onLongPress = value;
  }

  /// The handler for [SemanticsAction.scrollLeft].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from right to left. It should be recognized by controls that are
  /// horizontally scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping left with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// right and then left in one motion path. On Android, [onScrollUp] and
  /// [onScrollLeft] share the same gesture. Therefore, only on of them should
  /// be provided.
  VoidCallback get onScrollLeft => _onScrollLeft;
  VoidCallback _onScrollLeft;
  set onScrollLeft(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.scrollLeft, value);
    _onScrollLeft = value;
  }

  /// The handler for [SemanticsAction.dismiss].
  ///
  /// This is a request to dismiss the currently focused node.
  ///
  /// TalkBack users on Android can trigger this action in the local context
  /// menu, and VoiceOver users on iOS can trigger this action with a standard
  /// gesture or menu option.
  VoidCallback get onDismiss => _onDismiss;
  VoidCallback _onDismiss;
  set onDismiss(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.dismiss, value);
    _onDismiss = value;
  }

  /// The handler for [SemanticsAction.scrollRight].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from left to right. It should be recognized by controls that are
  /// horizontally scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping right with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// left and then right in one motion path. On Android, [onScrollDown] and
  /// [onScrollRight] share the same gesture. Therefore, only on of them should
  /// be provided.
  VoidCallback get onScrollRight => _onScrollRight;
  VoidCallback _onScrollRight;
  set onScrollRight(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.scrollRight, value);
    _onScrollRight = value;
  }

  /// The handler for [SemanticsAction.scrollUp].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from bottom to top. It should be recognized by controls that are
  /// vertically scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping up with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// right and then left in one motion path. On Android, [onScrollUp] and
  /// [onScrollLeft] share the same gesture. Therefore, only on of them should
  /// be provided.
  VoidCallback get onScrollUp => _onScrollUp;
  VoidCallback _onScrollUp;
  set onScrollUp(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.scrollUp, value);
    _onScrollUp = value;
  }

  /// The handler for [SemanticsAction.scrollDown].
  ///
  /// This is the semantic equivalent of a user moving their finger across the
  /// screen from top to bottom. It should be recognized by controls that are
  /// vertically scrollable.
  ///
  /// VoiceOver users on iOS can trigger this action by swiping down with three
  /// fingers. TalkBack users on Android can trigger this action by swiping
  /// left and then right in one motion path. On Android, [onScrollDown] and
  /// [onScrollRight] share the same gesture. Therefore, only on of them should
  /// be provided.
  VoidCallback get onScrollDown => _onScrollDown;
  VoidCallback _onScrollDown;
  set onScrollDown(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.scrollDown, value);
    _onScrollDown = value;
  }

  /// The handler for [SemanticsAction.increase].
  ///
  /// This is a request to increase the value represented by the widget. For
  /// example, this action might be recognized by a slider control.
  ///
  /// If a [value] is set, [increasedValue] must also be provided and
  /// [onIncrease] must ensure that [value] will be set to [increasedValue].
  ///
  /// VoiceOver users on iOS can trigger this action by swiping up with one
  /// finger. TalkBack users on Android can trigger this action by pressing the
  /// volume up button.
  VoidCallback get onIncrease => _onIncrease;
  VoidCallback _onIncrease;
  set onIncrease(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.increase, value);
    _onIncrease = value;
  }

  /// The handler for [SemanticsAction.decrease].
  ///
  /// This is a request to decrease the value represented by the widget. For
  /// example, this action might be recognized by a slider control.
  ///
  /// If a [value] is set, [decreasedValue] must also be provided and
  /// [onDecrease] must ensure that [value] will be set to [decreasedValue].
  ///
  /// VoiceOver users on iOS can trigger this action by swiping down with one
  /// finger. TalkBack users on Android can trigger this action by pressing the
  /// volume down button.
  VoidCallback get onDecrease => _onDecrease;
  VoidCallback _onDecrease;
  set onDecrease(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.decrease, value);
    _onDecrease = value;
  }

  /// The handler for [SemanticsAction.copy].
  ///
  /// This is a request to copy the current selection to the clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  VoidCallback get onCopy => _onCopy;
  VoidCallback _onCopy;
  set onCopy(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.copy, value);
    _onCopy = value;
  }

  /// The handler for [SemanticsAction.cut].
  ///
  /// This is a request to cut the current selection and place it in the
  /// clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  VoidCallback get onCut => _onCut;
  VoidCallback _onCut;
  set onCut(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.cut, value);
    _onCut = value;
  }

  /// The handler for [SemanticsAction.paste].
  ///
  /// This is a request to paste the current content of the clipboard.
  ///
  /// TalkBack users on Android can trigger this action from the local context
  /// menu of a text field, for example.
  VoidCallback get onPaste => _onPaste;
  VoidCallback _onPaste;
  set onPaste(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.paste, value);
    _onPaste = value;
  }

  /// The handler for [SemanticsAction.showOnScreen].
  ///
  /// A request to fully show the semantics node on screen. For example, this
  /// action might be send to a node in a scrollable list that is partially off
  /// screen to bring it on screen.
  ///
  /// For elements in a scrollable list the framework provides a default
  /// implementation for this action and it is not advised to provide a
  /// custom one via this setter.
  VoidCallback get onShowOnScreen => _onShowOnScreen;
  VoidCallback _onShowOnScreen;
  set onShowOnScreen(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.showOnScreen, value);
    _onShowOnScreen = value;
  }

  /// The handler for [SemanticsAction.onMoveCursorForwardByCharacter].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field forward by one character.
  ///
  /// TalkBack users can trigger this by pressing the volume up key while the
  /// input focus is in a text field.
  MoveCursorHandler get onMoveCursorForwardByCharacter => _onMoveCursorForwardByCharacter;
  MoveCursorHandler _onMoveCursorForwardByCharacter;
  set onMoveCursorForwardByCharacter(MoveCursorHandler value) {
    assert(value != null);
    _addAction(SemanticsAction.moveCursorForwardByCharacter, (dynamic args) {
      final bool extentSelection = args as bool;
      assert(extentSelection != null);
      value(extentSelection);
    });
    _onMoveCursorForwardByCharacter = value;
  }

  /// The handler for [SemanticsAction.onMoveCursorBackwardByCharacter].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one character.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  MoveCursorHandler get onMoveCursorBackwardByCharacter => _onMoveCursorBackwardByCharacter;
  MoveCursorHandler _onMoveCursorBackwardByCharacter;
  set onMoveCursorBackwardByCharacter(MoveCursorHandler value) {
    assert(value != null);
    _addAction(SemanticsAction.moveCursorBackwardByCharacter, (dynamic args) {
      final bool extentSelection = args as bool;
      assert(extentSelection != null);
      value(extentSelection);
    });
    _onMoveCursorBackwardByCharacter = value;
  }

  /// The handler for [SemanticsAction.onMoveCursorForwardByWord].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one word.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  MoveCursorHandler get onMoveCursorForwardByWord => _onMoveCursorForwardByWord;
  MoveCursorHandler _onMoveCursorForwardByWord;
  set onMoveCursorForwardByWord(MoveCursorHandler value) {
    assert(value != null);
    _addAction(SemanticsAction.moveCursorForwardByWord, (dynamic args) {
      final bool extentSelection = args as bool;
      assert(extentSelection != null);
      value(extentSelection);
    });
    _onMoveCursorForwardByCharacter = value;
  }

  /// The handler for [SemanticsAction.onMoveCursorBackwardByWord].
  ///
  /// This handler is invoked when the user wants to move the cursor in a
  /// text field backward by one word.
  ///
  /// TalkBack users can trigger this by pressing the volume down key while the
  /// input focus is in a text field.
  MoveCursorHandler get onMoveCursorBackwardByWord => _onMoveCursorBackwardByWord;
  MoveCursorHandler _onMoveCursorBackwardByWord;
  set onMoveCursorBackwardByWord(MoveCursorHandler value) {
    assert(value != null);
    _addAction(SemanticsAction.moveCursorBackwardByWord, (dynamic args) {
      final bool extentSelection = args as bool;
      assert(extentSelection != null);
      value(extentSelection);
    });
    _onMoveCursorBackwardByCharacter = value;
  }

  /// The handler for [SemanticsAction.setSelection].
  ///
  /// This handler is invoked when the user either wants to change the currently
  /// selected text in a text field or change the position of the cursor.
  ///
  /// TalkBack users can trigger this handler by selecting "Move cursor to
  /// beginning/end" or "Select all" from the local context menu.
  SetSelectionHandler get onSetSelection => _onSetSelection;
  SetSelectionHandler _onSetSelection;
  set onSetSelection(SetSelectionHandler value) {
    assert(value != null);
    _addAction(SemanticsAction.setSelection, (dynamic args) {
      assert(args != null && args is Map);
      final Map<String, int> selection = (args as Map<dynamic, dynamic>).cast<String, int>();
      assert(selection != null && selection['base'] != null && selection['extent'] != null);
      value(TextSelection(
        baseOffset: selection['base'],
        extentOffset: selection['extent'],
      ));
    });
    _onSetSelection = value;
  }

  /// The handler for [SemanticsAction.didGainAccessibilityFocus].
  ///
  /// This handler is invoked when the node annotated with this handler gains
  /// the accessibility focus. The accessibility focus is the
  /// green (on Android with TalkBack) or black (on iOS with VoiceOver)
  /// rectangle shown on screen to indicate what element an accessibility
  /// user is currently interacting with.
  ///
  /// The accessibility focus is different from the input focus. The input focus
  /// is usually held by the element that currently responds to keyboard inputs.
  /// Accessibility focus and input focus can be held by two different nodes!
  ///
  /// See also:
  ///
  ///  * [onDidLoseAccessibilityFocus], which is invoked when the accessibility
  ///    focus is removed from the node.
  ///  * [FocusNode], [FocusScope], [FocusManager], which manage the input focus.
  VoidCallback get onDidGainAccessibilityFocus => _onDidGainAccessibilityFocus;
  VoidCallback _onDidGainAccessibilityFocus;
  set onDidGainAccessibilityFocus(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.didGainAccessibilityFocus, value);
    _onDidGainAccessibilityFocus = value;
  }

  /// The handler for [SemanticsAction.didLoseAccessibilityFocus].
  ///
  /// This handler is invoked when the node annotated with this handler
  /// loses the accessibility focus. The accessibility focus is
  /// the green (on Android with TalkBack) or black (on iOS with VoiceOver)
  /// rectangle shown on screen to indicate what element an accessibility
  /// user is currently interacting with.
  ///
  /// The accessibility focus is different from the input focus. The input focus
  /// is usually held by the element that currently responds to keyboard inputs.
  /// Accessibility focus and input focus can be held by two different nodes!
  ///
  /// See also:
  ///
  ///  * [onDidGainAccessibilityFocus], which is invoked when the node gains
  ///    accessibility focus.
  ///  * [FocusNode], [FocusScope], [FocusManager], which manage the input focus.
  VoidCallback get onDidLoseAccessibilityFocus => _onDidLoseAccessibilityFocus;
  VoidCallback _onDidLoseAccessibilityFocus;
  set onDidLoseAccessibilityFocus(VoidCallback value) {
    _addArgumentlessAction(SemanticsAction.didLoseAccessibilityFocus, value);
    _onDidLoseAccessibilityFocus = value;
  }

  /// Returns the action handler registered for [action] or null if none was
  /// registered.
  ///
  /// See also:
  ///
  ///  * [addAction] to add an action.
  _SemanticsActionHandler getActionHandler(SemanticsAction action) => _actions[action];

  /// Determines the position of this node among its siblings in the traversal
  /// sort order.
  ///
  /// This is used to describe the order in which the semantic node should be
  /// traversed by the accessibility services on the platform (e.g. VoiceOver
  /// on iOS and TalkBack on Android).
  ///
  /// Whether this sort key has an effect on the [SemanticsNode] sort order is
  /// subject to how this configuration is used. For example, the [absorb]
  /// method may decide to not use this key when it combines multiple
  /// [SemanticsConfiguration] objects.
  SemanticsSortKey get sortKey => _sortKey;
  SemanticsSortKey _sortKey;
  set sortKey(SemanticsSortKey value) {
    assert(value != null);
    _sortKey = value;
    _hasBeenAnnotated = true;
  }

  /// The index of this node within the parent's list of semantic children.
  ///
  /// This includes all semantic nodes, not just those currently in the
  /// child list. For example, if a scrollable has five children but the first
  /// two are not visible (and thus not included in the list of children), then
  /// the index of the last node will still be 4.
  int get indexInParent => _indexInParent;
  int _indexInParent;
  set indexInParent(int value) {
    _indexInParent = value;
    _hasBeenAnnotated = true;
  }

  /// The total number of scrollable children that contribute to semantics.
  ///
  /// If the number of children are unknown or unbounded, this value will be
  /// null.
  int get scrollChildCount => _scrollChildCount;
  int _scrollChildCount;
  set scrollChildCount(int value) {
    if (value == scrollChildCount)
      return;
    _scrollChildCount = value;
    _hasBeenAnnotated = true;
  }

  /// The index of the first visible scrollable child that contributes to
  /// semantics.
  int get scrollIndex => _scrollIndex;
  int _scrollIndex;
  set scrollIndex(int value) {
    if (value == scrollIndex)
      return;
    _scrollIndex = value;
    _hasBeenAnnotated = true;
  }

  /// The id of the platform view, whose semantics nodes will be added as
  /// children to this node.
  int get platformViewId => _platformViewId;
  int _platformViewId;
  set platformViewId(int value) {
    if (value == platformViewId)
      return;
    _platformViewId = value;
    _hasBeenAnnotated = true;
  }

  /// The maximum number of characters that can be entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [isTextField] is true. Defaults to null,
  /// which means no limit is imposed on the text field.
  int get maxValueLength => _maxValueLength;
  int _maxValueLength;
  set maxValueLength(int value) {
    if (value == maxValueLength)
      return;
    _maxValueLength = value;
    _hasBeenAnnotated = true;
  }

  /// The current number of characters that have been entered into an editable
  /// text field.
  ///
  /// For the purpose of this function a character is defined as one Unicode
  /// scalar value.
  ///
  /// This should only be set when [isTextField] is true. Must be set when
  /// [maxValueLength] is set.
  int get currentValueLength => _currentValueLength;
  int _currentValueLength;
  set currentValueLength(int value) {
    if (value == currentValueLength)
      return;
    _currentValueLength = value;
    _hasBeenAnnotated = true;
  }

  /// Whether the semantic information provided by the owning [RenderObject] and
  /// all of its descendants should be treated as one logical entity.
  ///
  /// If set to true, the descendants of the owning [RenderObject]'s
  /// [SemanticsNode] will merge their semantic information into the
  /// [SemanticsNode] representing the owning [RenderObject].
  ///
  /// Setting this to true requires that [isSemanticBoundary] is also true.
  bool get isMergingSemanticsOfDescendants => _isMergingSemanticsOfDescendants;
  bool _isMergingSemanticsOfDescendants = false;
  set isMergingSemanticsOfDescendants(bool value) {
    assert(isSemanticBoundary);
    _isMergingSemanticsOfDescendants = value;
    _hasBeenAnnotated = true;
  }

  /// The handlers for each supported [CustomSemanticsAction].
  ///
  /// Whenever a custom accessibility action is added to a node, the action
  /// [SemanticAction.customAction] is automatically added. A handler is
  /// created which uses the passed argument to lookup the custom action
  /// handler from this map and invoke it, if present.
  Map<CustomSemanticsAction, VoidCallback> get customSemanticsActions => _customSemanticsActions;
  Map<CustomSemanticsAction, VoidCallback> _customSemanticsActions = <CustomSemanticsAction, VoidCallback>{};
  set customSemanticsActions(Map<CustomSemanticsAction, VoidCallback> value) {
    _hasBeenAnnotated = true;
    _actionsAsBits |= SemanticsAction.customAction.index;
    _customSemanticsActions = value;
    _actions[SemanticsAction.customAction] = _onCustomSemanticsAction;
  }

  void _onCustomSemanticsAction(dynamic args) {
    final CustomSemanticsAction action = CustomSemanticsAction.getAction(args as int);
    if (action == null)
      return;
    final VoidCallback callback = _customSemanticsActions[action];
    if (callback != null)
      callback();
  }

  /// A textual description of the owning [RenderObject].
  ///
  /// On iOS this is used for the `accessibilityLabel` property defined in the
  /// `UIAccessibility` Protocol. On Android it is concatenated together with
  /// [value] and [hint] in the following order: [value], [label], [hint].
  /// The concatenated value is then used as the `Text` description.
  ///
  /// The reading direction is given by [textDirection].
  String get label => _label;
  String _label = '';
  set label(String label) {
    assert(label != null);
    _label = label;
    _hasBeenAnnotated = true;
  }

  /// A textual description for the current value of the owning [RenderObject].
  ///
  /// On iOS this is used for the `accessibilityValue` property defined in the
  /// `UIAccessibility` Protocol. On Android it is concatenated together with
  /// [label] and [hint] in the following order: [value], [label], [hint].
  /// The concatenated value is then used as the `Text` description.
  ///
  /// The reading direction is given by [textDirection].
  ///
  /// See also:
  ///
  ///  * [decreasedValue], describes what [value] will be after performing
  ///    [SemanticsAction.decrease].
  ///  * [increasedValue], describes what [value] will be after performing
  ///    [SemanticsAction.increase].
  String get value => _value;
  String _value = '';
  set value(String value) {
    assert(value != null);
    _value = value;
    _hasBeenAnnotated = true;
  }

  /// The value that [value] will have after performing a
  /// [SemanticsAction.decrease] action.
  ///
  /// This must be set if a handler for [SemanticsAction.decrease] is provided
  /// and [value] is set.
  ///
  /// The reading direction is given by [textDirection].
  String get decreasedValue => _decreasedValue;
  String _decreasedValue = '';
  set decreasedValue(String decreasedValue) {
    assert(decreasedValue != null);
    _decreasedValue = decreasedValue;
    _hasBeenAnnotated = true;
  }

  /// The value that [value] will have after performing a
  /// [SemanticsAction.increase] action.
  ///
  /// This must be set if a handler for [SemanticsAction.increase] is provided
  /// and [value] is set.
  ///
  /// The reading direction is given by [textDirection].
  String get increasedValue => _increasedValue;
  String _increasedValue = '';
  set increasedValue(String increasedValue) {
    assert(increasedValue != null);
    _increasedValue = increasedValue;
    _hasBeenAnnotated = true;
  }

  /// A brief description of the result of performing an action on this node.
  ///
  /// On iOS this is used for the `accessibilityHint` property defined in the
  /// `UIAccessibility` Protocol. On Android it is concatenated together with
  /// [label] and [value] in the following order: [value], [label], [hint].
  /// The concatenated value is then used as the `Text` description.
  ///
  /// The reading direction is given by [textDirection].
  String get hint => _hint;
  String _hint = '';
  set hint(String hint) {
    assert(hint != null);
    _hint = hint;
    _hasBeenAnnotated = true;
  }

  /// Provides hint values which override the default hints on supported
  /// platforms.
  SemanticsHintOverrides get hintOverrides => _hintOverrides;
  SemanticsHintOverrides _hintOverrides;
  set hintOverrides(SemanticsHintOverrides value) {
    if (value == null)
      return;
    _hintOverrides = value;
    _hasBeenAnnotated = true;
  }

  /// The elevation in z-direction at which the owning [RenderObject] is
  /// located relative to its parent.
  double get elevation => _elevation;
  double _elevation = 0.0;
  set elevation(double value) {
    assert(value != null && value >= 0.0);
    if (value == _elevation) {
      return;
    }
    _elevation = value;
    _hasBeenAnnotated = true;
  }

  /// The extend that the owning [RenderObject] occupies in z-direction starting
  /// at [elevation].
  ///
  /// It's extremely rare to set this value directly. Instead, it is calculated
  /// implicitly when other [SemanticsConfiguration]s are merged into this one
  /// via [absorb].
  double get thickness => _thickness;
  double _thickness = 0.0;
  set thickness(double value) {
    assert(value != null && value >= 0.0);
    if (value == _thickness) {
      return;
    }
    _thickness = value;
    _hasBeenAnnotated = true;
  }

  /// Whether the semantics node is the root of a subtree for which values
  /// should be announced.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.scopesRoute], for a full description of route scoping.
  bool get scopesRoute => _hasFlag(SemanticsFlag.scopesRoute);
  set scopesRoute(bool value) {
    _setFlag(SemanticsFlag.scopesRoute, value);
  }

  /// Whether the semantics node contains the label of a route.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.namesRoute], for a full description of route naming.
  bool get namesRoute => _hasFlag(SemanticsFlag.namesRoute);
  set namesRoute(bool value) {
    _setFlag(SemanticsFlag.namesRoute, value);
  }

  /// Whether the semantics node represents an image.
  bool get isImage => _hasFlag(SemanticsFlag.isImage);
  set isImage(bool value) {
    _setFlag(SemanticsFlag.isImage, value);
  }

  /// Whether the semantics node is a live region.
  ///
  /// On Android, when the label changes on a live region semantics node,
  /// TalkBack will make a polite announcement of the current label. This
  /// announcement occurs even if the node is not focused, but only if the label
  /// has changed since the last update.
  ///
  /// An example of a live region is the [Snackbar] widget. When it appears
  /// on the screen it may be difficult to focus to read the label. A live
  /// region causes an initial polite announcement to be generated
  /// automatically.
  ///
  /// See also:
  ///
  ///  * [SemanticsFlag.isLiveRegion], the semantics flag that this setting controls.
  bool get liveRegion => _hasFlag(SemanticsFlag.isLiveRegion);
  set liveRegion(bool value) {
    _setFlag(SemanticsFlag.isLiveRegion, value);
  }

  /// The reading direction for the text in [label], [value], [hint],
  /// [increasedValue], and [decreasedValue].
  TextDirection get textDirection => _textDirection;
  TextDirection _textDirection;
  set textDirection(TextDirection textDirection) {
    _textDirection = textDirection;
    _hasBeenAnnotated = true;
  }

  /// Whether the owning [RenderObject] is selected (true) or not (false).
  ///
  /// This is different from having accessibility focus. The element that is
  /// accessibility focused may or may not be selected; e.g. a [ListTile] can have
  /// accessibility focus but have its [ListTile.selected] property set to false,
  /// in which case it will not be flagged as selected.
  bool get isSelected => _hasFlag(SemanticsFlag.isSelected);
  set isSelected(bool value) {
    _setFlag(SemanticsFlag.isSelected, value);
  }

  /// Whether the owning [RenderObject] is currently enabled.
  ///
  /// A disabled object does not respond to user interactions. Only objects that
  /// usually respond to user interactions, but which currently do not (like a
  /// disabled button) should be marked as disabled.
  ///
  /// The setter should not be called for objects (like static text) that never
  /// respond to user interactions.
  ///
  /// The getter will return null if the owning [RenderObject] doesn't support
  /// the concept of being enabled/disabled.
  ///
  /// This property does not control whether semantics are enabled. If you wish to
  /// disable semantics for a particular widget, you should use an [ExcludeSemantics]
  /// widget.
  bool get isEnabled => _hasFlag(SemanticsFlag.hasEnabledState) ? _hasFlag(SemanticsFlag.isEnabled) : null;
  set isEnabled(bool value) {
    _setFlag(SemanticsFlag.hasEnabledState, true);
    _setFlag(SemanticsFlag.isEnabled, value);
  }

  /// If this node has Boolean state that can be controlled by the user, whether
  /// that state is checked or unchecked, corresponding to true and false,
  /// respectively.
  ///
  /// Do not call the setter for this field if the owning [RenderObject] doesn't
  /// have checked/unchecked state that can be controlled by the user.
  ///
  /// The getter returns null if the owning [RenderObject] does not have
  /// checked/unchecked state.
  bool get isChecked => _hasFlag(SemanticsFlag.hasCheckedState) ? _hasFlag(SemanticsFlag.isChecked) : null;
  set isChecked(bool value) {
    _setFlag(SemanticsFlag.hasCheckedState, true);
    _setFlag(SemanticsFlag.isChecked, value);
  }

  /// If this node has Boolean state that can be controlled by the user, whether
  /// that state is on or off, corresponding to true and false, respectively.
  ///
  /// Do not call the setter for this field if the owning [RenderObject] doesn't
  /// have on/off state that can be controlled by the user.
  ///
  /// The getter returns null if the owning [RenderObject] does not have
  /// on/off state.
  bool get isToggled => _hasFlag(SemanticsFlag.hasToggledState) ? _hasFlag(SemanticsFlag.isToggled) : null;
  set isToggled(bool value) {
    _setFlag(SemanticsFlag.hasToggledState, true);
    _setFlag(SemanticsFlag.isToggled, value);
  }

  /// Whether the owning RenderObject corresponds to UI that allows the user to
  /// pick one of several mutually exclusive options.
  ///
  /// For example, a [Radio] button is in a mutually exclusive group because
  /// only one radio button in that group can be marked as [isChecked].
  bool get isInMutuallyExclusiveGroup => _hasFlag(SemanticsFlag.isInMutuallyExclusiveGroup);
  set isInMutuallyExclusiveGroup(bool value) {
    _setFlag(SemanticsFlag.isInMutuallyExclusiveGroup, value);
  }

  /// Whether the owning [RenderObject] can hold the input focus.
  bool get isFocusable => _hasFlag(SemanticsFlag.isFocusable);
  set isFocusable(bool value) {
    _setFlag(SemanticsFlag.isFocusable, value);
  }

  /// Whether the owning [RenderObject] currently holds the input focus.
  bool get isFocused => _hasFlag(SemanticsFlag.isFocused);
  set isFocused(bool value) {
    _setFlag(SemanticsFlag.isFocused, value);
  }

  /// Whether the owning [RenderObject] is a button (true) or not (false).
  bool get isButton => _hasFlag(SemanticsFlag.isButton);
  set isButton(bool value) {
    _setFlag(SemanticsFlag.isButton, value);
  }

  /// Whether the owning [RenderObject] is a link (true) or not (false).
  bool get isLink => _hasFlag(SemanticsFlag.isLink);
  set isLink(bool value) {
    _setFlag(SemanticsFlag.isLink, value);
  }

  /// Whether the owning [RenderObject] is a header (true) or not (false).
  bool get isHeader => _hasFlag(SemanticsFlag.isHeader);
  set isHeader(bool value) {
    _setFlag(SemanticsFlag.isHeader, value);
  }

  /// Whether the owning [RenderObject] is considered hidden.
  ///
  /// Hidden elements are currently not visible on screen. They may be covered
  /// by other elements or positioned outside of the visible area of a viewport.
  ///
  /// Hidden elements cannot gain accessibility focus though regular touch. The
  /// only way they can be focused is by moving the focus to them via linear
  /// navigation.
  ///
  /// Platforms are free to completely ignore hidden elements and new platforms
  /// are encouraged to do so.
  ///
  /// Instead of marking an element as hidden it should usually be excluded from
  /// the semantics tree altogether. Hidden elements are only included in the
  /// semantics tree to work around platform limitations and they are mainly
  /// used to implement accessibility scrolling on iOS.
  bool get isHidden => _hasFlag(SemanticsFlag.isHidden);
  set isHidden(bool value) {
    _setFlag(SemanticsFlag.isHidden, value);
  }

  /// Whether the owning [RenderObject] is a text field.
  bool get isTextField => _hasFlag(SemanticsFlag.isTextField);
  set isTextField(bool value) {
    _setFlag(SemanticsFlag.isTextField, value);
  }

  /// Whether the owning [RenderObject] is read only.
  ///
  /// Only applicable when [isTextField] is true.
  bool get isReadOnly => _hasFlag(SemanticsFlag.isReadOnly);
  set isReadOnly(bool value) {
    _setFlag(SemanticsFlag.isReadOnly, value);
  }

  /// Whether the [value] should be obscured.
  ///
  /// This option is usually set in combination with [textField] to indicate
  /// that the text field contains a password (or other sensitive information).
  /// Doing so instructs screen readers to not read out the [value].
  bool get isObscured => _hasFlag(SemanticsFlag.isObscured);
  set isObscured(bool value) {
    _setFlag(SemanticsFlag.isObscured, value);
  }

  /// Whether the text field is multiline.
  ///
  /// This option is usually set in combination with [textField] to indicate
  /// that the text field is configured to be multiline.
  bool get isMultiline => _hasFlag(SemanticsFlag.isMultiline);
  set isMultiline(bool value) {
    _setFlag(SemanticsFlag.isMultiline, value);
  }

  /// Whether the platform can scroll the semantics node when the user attempts
  /// to move focus to an offscreen child.
  ///
  /// For example, a [ListView] widget has implicit scrolling so that users can
  /// easily move to the next visible set of children. A [TabBar] widget does
  /// not have implicit scrolling, so that users can navigate into the tab
  /// body when reaching the end of the tab bar.
  bool get hasImplicitScrolling => _hasFlag(SemanticsFlag.hasImplicitScrolling);
  set hasImplicitScrolling(bool value) {
    _setFlag(SemanticsFlag.hasImplicitScrolling, value);
  }

  /// The currently selected text (or the position of the cursor) within [value]
  /// if this node represents a text field.
  TextSelection get textSelection => _textSelection;
  TextSelection _textSelection;
  set textSelection(TextSelection value) {
    assert(value != null);
    _textSelection = value;
    _hasBeenAnnotated = true;
  }

  /// Indicates the current scrolling position in logical pixels if the node is
  /// scrollable.
  ///
  /// The properties [scrollExtentMin] and [scrollExtentMax] indicate the valid
  /// in-range values for this property. The value for [scrollPosition] may
  /// (temporarily) be outside that range, e.g. during an overscroll.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.pixels], from where this value is usually taken.
  double get scrollPosition => _scrollPosition;
  double _scrollPosition;
  set scrollPosition(double value) {
    assert(value != null);
    _scrollPosition = value;
    _hasBeenAnnotated = true;
  }

  /// Indicates the maximum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.maxScrollExtent], from where this value is usually taken.
  double get scrollExtentMax => _scrollExtentMax;
  double _scrollExtentMax;
  set scrollExtentMax(double value) {
    assert(value != null);
    _scrollExtentMax = value;
    _hasBeenAnnotated = true;
  }

  /// Indicates the minimum in-range value for [scrollPosition] if the node is
  /// scrollable.
  ///
  /// This value may be infinity if the scroll is unbound.
  ///
  /// See also:
  ///
  ///  * [ScrollPosition.minScrollExtent], from where this value is usually taken.
  double get scrollExtentMin => _scrollExtentMin;
  double _scrollExtentMin;
  set scrollExtentMin(double value) {
    assert(value != null);
    _scrollExtentMin = value;
    _hasBeenAnnotated = true;
  }

  // TAGS

  /// The set of tags that this configuration wants to add to all child
  /// [SemanticsNode]s.
  ///
  /// See also:
  ///
  ///  * [addTagForChildren] to add a tag and for more information about their
  ///    usage.
  Iterable<SemanticsTag> get tagsForChildren => _tagsForChildren;
  Set<SemanticsTag> _tagsForChildren;

  /// Specifies a [SemanticsTag] that this configuration wants to apply to all
  /// child [SemanticsNode]s.
  ///
  /// The tag is added to all [SemanticsNode] that pass through the
  /// [RenderObject] owning this configuration while looking to be attached to a
  /// parent [SemanticsNode].
  ///
  /// Tags are used to communicate to a parent [SemanticsNode] that a child
  /// [SemanticsNode] was passed through a particular [RenderObject]. The parent
  /// can use this information to determine the shape of the semantics tree.
  ///
  /// See also:
  ///
  ///  * [RenderSemanticsGestureHandler.excludeFromScrolling] for an example of
  ///    how tags are used.
  void addTagForChildren(SemanticsTag tag) {
    _tagsForChildren ??= <SemanticsTag>{};
    _tagsForChildren.add(tag);
  }

  // INTERNAL FLAG MANAGEMENT

  int _flags = 0;
  void _setFlag(SemanticsFlag flag, bool value) {
    if (value) {
      _flags |= flag.index;
    } else {
      _flags &= ~flag.index;
    }
    _hasBeenAnnotated = true;
  }

  bool _hasFlag(SemanticsFlag flag) => (_flags & flag.index) != 0;

  // CONFIGURATION COMBINATION LOGIC

  /// Whether this configuration is compatible with the provided `other`
  /// configuration.
  ///
  /// Two configurations are said to be compatible if they can be added to the
  /// same [SemanticsNode] without losing any semantics information.
  bool isCompatibleWith(SemanticsConfiguration other) {
    if (other == null || !other.hasBeenAnnotated || !hasBeenAnnotated)
      return true;
    if (_actionsAsBits & other._actionsAsBits != 0)
      return false;
    if ((_flags & other._flags) != 0)
      return false;
    if (_platformViewId != null && other._platformViewId != null) {
      return false;
    }
    if (_maxValueLength != null && other._maxValueLength != null) {
      return false;
    }
    if (_currentValueLength != null && other._currentValueLength != null) {
      return false;
    }
    if (_value != null && _value.isNotEmpty && other._value != null && other._value.isNotEmpty)
      return false;
    return true;
  }

  /// Absorb the semantic information from `child` into this configuration.
  ///
  /// This adds the semantic information of both configurations and saves the
  /// result in this configuration.
  ///
  /// The [RenderObject] owning the `child` configuration must be a descendant
  /// of the [RenderObject] that owns this configuration.
  ///
  /// Only configurations that have [explicitChildNodes] set to false can
  /// absorb other configurations and it is recommended to only absorb compatible
  /// configurations as determined by [isCompatibleWith].
  void absorb(SemanticsConfiguration child) {
    assert(!explicitChildNodes);

    if (!child.hasBeenAnnotated)
      return;

    _actions.addAll(child._actions);
    _customSemanticsActions.addAll(child._customSemanticsActions);
    _actionsAsBits |= child._actionsAsBits;
    _flags |= child._flags;
    _textSelection ??= child._textSelection;
    _scrollPosition ??= child._scrollPosition;
    _scrollExtentMax ??= child._scrollExtentMax;
    _scrollExtentMin ??= child._scrollExtentMin;
    _hintOverrides ??= child._hintOverrides;
    _indexInParent ??= child.indexInParent;
    _scrollIndex ??= child._scrollIndex;
    _scrollChildCount ??= child._scrollChildCount;
    _platformViewId ??= child._platformViewId;
    _maxValueLength ??= child._maxValueLength;
    _currentValueLength ??= child._currentValueLength;

    textDirection ??= child.textDirection;
    _sortKey ??= child._sortKey;
    _label = _concatStrings(
      thisString: _label,
      thisTextDirection: textDirection,
      otherString: child._label,
      otherTextDirection: child.textDirection,
    );
    if (_decreasedValue == '' || _decreasedValue == null)
      _decreasedValue = child._decreasedValue;
    if (_value == '' || _value == null)
      _value = child._value;
    if (_increasedValue == '' || _increasedValue == null)
      _increasedValue = child._increasedValue;
    _hint = _concatStrings(
      thisString: _hint,
      thisTextDirection: textDirection,
      otherString: child._hint,
      otherTextDirection: child.textDirection,
    );

    _thickness = math.max(_thickness, child._thickness + child._elevation);

    _hasBeenAnnotated = _hasBeenAnnotated || child._hasBeenAnnotated;
  }

  /// Returns an exact copy of this configuration.
  SemanticsConfiguration copy() {
    return SemanticsConfiguration()
      .._isSemanticBoundary = _isSemanticBoundary
      ..explicitChildNodes = explicitChildNodes
      ..isBlockingSemanticsOfPreviouslyPaintedNodes = isBlockingSemanticsOfPreviouslyPaintedNodes
      .._hasBeenAnnotated = _hasBeenAnnotated
      .._isMergingSemanticsOfDescendants = _isMergingSemanticsOfDescendants
      .._textDirection = _textDirection
      .._sortKey = _sortKey
      .._label = _label
      .._increasedValue = _increasedValue
      .._value = _value
      .._decreasedValue = _decreasedValue
      .._hint = _hint
      .._hintOverrides = _hintOverrides
      .._elevation = _elevation
      .._thickness = _thickness
      .._flags = _flags
      .._tagsForChildren = _tagsForChildren
      .._textSelection = _textSelection
      .._scrollPosition = _scrollPosition
      .._scrollExtentMax = _scrollExtentMax
      .._scrollExtentMin = _scrollExtentMin
      .._actionsAsBits = _actionsAsBits
      .._indexInParent = indexInParent
      .._scrollIndex = _scrollIndex
      .._scrollChildCount = _scrollChildCount
      .._platformViewId = _platformViewId
      .._maxValueLength = _maxValueLength
      .._currentValueLength = _currentValueLength
      .._actions.addAll(_actions)
      .._customSemanticsActions.addAll(_customSemanticsActions);
  }
}

/// Used by [debugDumpSemanticsTree] to specify the order in which child nodes
/// are printed.
enum DebugSemanticsDumpOrder {
  /// Print nodes in inverse hit test order.
  ///
  /// In inverse hit test order, the last child of a [SemanticsNode] will be
  /// asked first if it wants to respond to a user's interaction, followed by
  /// the second last, etc. until a taker is found.
  inverseHitTest,

  /// Print nodes in semantic traversal order.
  ///
  /// This is the order in which a user would navigate the UI using the "next"
  /// and "previous" gestures.
  traversalOrder,
}

String _concatStrings({
  @required String thisString,
  @required String otherString,
  @required TextDirection thisTextDirection,
  @required TextDirection otherTextDirection,
}) {
  if (otherString.isEmpty)
    return thisString;
  String nestedLabel = otherString;
  if (thisTextDirection != otherTextDirection && otherTextDirection != null) {
    switch (otherTextDirection) {
      case TextDirection.rtl:
        nestedLabel = '${Unicode.RLE}$nestedLabel${Unicode.PDF}';
        break;
      case TextDirection.ltr:
        nestedLabel = '${Unicode.LRE}$nestedLabel${Unicode.PDF}';
        break;
    }
  }
  if (thisString.isEmpty)
    return nestedLabel;
  return '$thisString\n$nestedLabel';
}

/// Base class for all sort keys for [SemanticsProperties.sortKey] accessibility
/// traversal order sorting.
///
/// Sort keys are sorted by [name], then by the comparison that the subclass
/// implements. If [SemanticsProperties.sortKey] is specified, sort keys within
/// the same semantic group must all be of the same type.
///
/// Keys with no [name] are compared to other keys with no [name], and will
/// be traversed before those with a [name].
///
/// If no sort key is applied to a semantics node, then it will be ordered using
/// a platform dependent default algorithm.
///
/// See also:
///
///  * [OrdinalSortKey] for a sort key that sorts using an ordinal.
abstract class SemanticsSortKey with Diagnosticable implements Comparable<SemanticsSortKey> {
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
  const SemanticsSortKey({this.name});

  /// An optional name that will group this sort key with other sort keys of the
  /// same [name].
  ///
  /// Sort keys must have the same `runtimeType` when compared.
  ///
  /// Keys with no [name] are compared to other keys with no [name], and will
  /// be traversed before those with a [name].
  final String name;

  @override
  int compareTo(SemanticsSortKey other) {
    // Sort by name first and then subclass ordering.
    assert(runtimeType == other.runtimeType, 'Semantics sort keys can only be compared to other sort keys of the same type.');

    // Defer to the subclass implementation for ordering only if the names are
    // identical (or both null).
    if (name == other.name) {
      return doCompare(other);
    }

    // Keys that don't have a name are sorted together and come before those with
    // a name.
    if (name == null && other.name != null) {
      return -1;
    } else if (name != null && other.name == null) {
      return 1;
    }

    return name.compareTo(other.name);
  }

  /// The implementation of [compareTo].
  ///
  /// The argument is guaranteed to be of the same type as this object and have
  /// the same [name].
  ///
  /// The method should return a negative number if this object comes earlier in
  /// the sort order than the argument; and a positive number if it comes later
  /// in the sort order. Returning zero causes the system to use default sort
  /// order.
  @protected
  int doCompare(covariant SemanticsSortKey other);

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('name', name, defaultValue: null));
  }
}

/// A [SemanticsSortKey] that sorts simply based on the `double` value it is
/// given.
///
/// The [OrdinalSortKey] compares itself with other [OrdinalSortKey]s
/// to sort based on the order it is given.
///
/// [OrdinalSortKey]s are sorted by the optional [name], then by their [order].
/// If [SemanticsProperties.sortKey] is a [OrdinalSortKey], then all the other
/// speficied sort keys in the same semantics group must also be
/// [OrdinalSortKey]s.
///
/// Keys with no [name] are compared to other keys with no [name], and will
/// be traversed before those with a [name].
///
/// The ordinal value [order] is typically a whole number, though it can be
/// fractional, e.g. in order to fit between two other consecutive whole
/// numbers. The value must be finite (it cannot be [double.nan],
/// [double.infinity], or [double.negativeInfinity]).
class OrdinalSortKey extends SemanticsSortKey {
  /// Creates a const semantics sort key that uses a [double] as its key value.
  ///
  /// The [order] must be a finite number, and must not be null.
  const OrdinalSortKey(
    this.order, {
    String name,
  }) : assert(order != null),
       assert(order != double.nan),
       assert(order > double.negativeInfinity),
       assert(order < double.infinity),
       super(name: name);

  /// Determines the placement of this key in a sequence of keys that defines
  /// the order in which this node is traversed by the platform's accessibility
  /// services.
  ///
  /// Lower values will be traversed first. Keys with the same [name] will be
  /// grouped together and sorted by name first, and then sorted by [order].
  final double order;

  @override
  int doCompare(OrdinalSortKey other) {
    if (other.order == null || order == null || other.order == order)
      return 0;
    return order.compareTo(other.order);
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DoubleProperty('order', order, defaultValue: null));
  }
}
