// 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.

/// @docImport 'package:flutter/material.dart';
///
/// @docImport 'page_storage.dart';
/// @docImport 'page_view.dart';
/// @docImport 'scroll_metrics.dart';
/// @docImport 'scroll_notification.dart';
/// @docImport 'scroll_view.dart';
/// @docImport 'single_child_scroll_view.dart';
/// @docImport 'two_dimensional_scroll_view.dart';
/// @docImport 'two_dimensional_viewport.dart';
library;

import 'dart:async';
import 'dart:math' as math;

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';

import 'basic.dart';
import 'framework.dart';
import 'gesture_detector.dart';
import 'media_query.dart';
import 'notification_listener.dart';
import 'restoration.dart';
import 'restoration_properties.dart';
import 'scroll_activity.dart';
import 'scroll_configuration.dart';
import 'scroll_context.dart';
import 'scroll_controller.dart';
import 'scroll_physics.dart';
import 'scroll_position.dart';
import 'scrollable_helpers.dart';
import 'selectable_region.dart';
import 'selection_container.dart';
import 'ticker_provider.dart';
import 'view.dart';
import 'viewport.dart';

export 'package:flutter/physics.dart' show Tolerance;

// Examples can assume:
// late BuildContext context;

/// Signature used by [Scrollable] to build the viewport through which the
/// scrollable content is displayed.
typedef ViewportBuilder = Widget Function(BuildContext context, ViewportOffset position);

/// Signature used by [TwoDimensionalScrollable] to build the viewport through
/// which the scrollable content is displayed.
typedef TwoDimensionalViewportBuilder =
    Widget Function(
      BuildContext context,
      ViewportOffset verticalPosition,
      ViewportOffset horizontalPosition,
    );

// The return type of _performEnsureVisible.
//
// The list of futures represents each pending ScrollPosition call to
// ensureVisible. The returned ScrollableState's context is used to find the
// next potential ancestor Scrollable.
typedef _EnsureVisibleResults = (List<Future<void>>, ScrollableState);

/// A widget that manages scrolling in one dimension and informs the [Viewport]
/// through which the content is viewed.
///
/// [Scrollable] implements the interaction model for a scrollable widget,
/// including gesture recognition, but does not have an opinion about how the
/// viewport, which actually displays the children, is constructed.
///
/// It's rare to construct a [Scrollable] directly. Instead, consider [ListView]
/// or [GridView], which combine scrolling, viewporting, and a layout model. To
/// combine layout models (or to use a custom layout mode), consider using
/// [CustomScrollView].
///
/// The static [Scrollable.of] and [Scrollable.ensureVisible] functions are
/// often used to interact with the [Scrollable] widget inside a [ListView] or
/// a [GridView].
///
/// To further customize scrolling behavior with a [Scrollable]:
///
/// 1. You can provide a [viewportBuilder] to customize the child model. For
///    example, [SingleChildScrollView] uses a viewport that displays a single
///    box child whereas [CustomScrollView] uses a [Viewport] or a
///    [ShrinkWrappingViewport], both of which display a list of slivers.
///
/// 2. You can provide a custom [ScrollController] that creates a custom
///    [ScrollPosition] subclass. For example, [PageView] uses a
///    [PageController], which creates a page-oriented scroll position subclass
///    that keeps the same page visible when the [Scrollable] resizes.
///
/// ## Persisting the scroll position during a session
///
/// Scrollables attempt to persist their scroll position using [PageStorage].
/// This can be disabled by setting [ScrollController.keepScrollOffset] to false
/// on the [controller]. If it is enabled, using a [PageStorageKey] for the
/// [key] of this widget (or one of its ancestors, e.g. a [ScrollView]) is
/// recommended to help disambiguate different [Scrollable]s from each other.
///
/// See also:
///
///  * [ListView], which is a commonly used [ScrollView] that displays a
///    scrolling, linear list of child widgets.
///  * [PageView], which is a scrolling list of child widgets that are each the
///    size of the viewport.
///  * [GridView], which is a [ScrollView] that displays a scrolling, 2D array
///    of child widgets.
///  * [CustomScrollView], which is a [ScrollView] that creates custom scroll
///    effects using slivers.
///  * [SingleChildScrollView], which is a scrollable widget that has a single
///    child.
///  * [ScrollNotification] and [NotificationListener], which can be used to watch
///    the scroll position without using a [ScrollController].
class Scrollable extends StatefulWidget {
  /// Creates a widget that scrolls.
  const Scrollable({
    super.key,
    this.axisDirection = AxisDirection.down,
    this.controller,
    this.physics,
    required this.viewportBuilder,
    this.incrementCalculator,
    this.excludeFromSemantics = false,
    this.semanticChildCount,
    this.dragStartBehavior = DragStartBehavior.start,
    this.restorationId,
    this.scrollBehavior,
    this.clipBehavior = Clip.hardEdge,
    this.hitTestBehavior = HitTestBehavior.opaque,
  }) : assert(semanticChildCount == null || semanticChildCount >= 0);

  /// {@template flutter.widgets.Scrollable.axisDirection}
  /// The direction in which this widget scrolls.
  ///
  /// For example, if the [Scrollable.axisDirection] is [AxisDirection.down],
  /// increasing the scroll position will cause content below the bottom of the
  /// viewport to become visible through the viewport. Similarly, if the
  /// axisDirection is [AxisDirection.right], increasing the scroll position
  /// will cause content beyond the right edge of the viewport to become visible
  /// through the viewport.
  ///
  /// Defaults to [AxisDirection.down].
  /// {@endtemplate}
  final AxisDirection axisDirection;

  /// {@template flutter.widgets.Scrollable.controller}
  /// An object that can be used to control the position to which this widget is
  /// scrolled.
  ///
  /// A [ScrollController] serves several purposes. It can be used to control
  /// the initial scroll position (see [ScrollController.initialScrollOffset]).
  /// It can be used to control whether the scroll view should automatically
  /// save and restore its scroll position in the [PageStorage] (see
  /// [ScrollController.keepScrollOffset]). It can be used to read the current
  /// scroll position (see [ScrollController.offset]), or change it (see
  /// [ScrollController.animateTo]).
  ///
  /// If null, a [ScrollController] will be created internally by [Scrollable]
  /// in order to create and manage the [ScrollPosition].
  ///
  /// See also:
  ///
  ///  * [Scrollable.ensureVisible], which animates the scroll position to
  ///    reveal a given [BuildContext].
  /// {@endtemplate}
  final ScrollController? controller;

  /// {@template flutter.widgets.Scrollable.physics}
  /// How the widgets should respond to user input.
  ///
  /// For example, determines how the widget continues to animate after the
  /// user stops dragging the scroll view.
  ///
  /// Defaults to matching platform conventions via the physics provided from
  /// the ambient [ScrollConfiguration].
  ///
  /// If an explicit [ScrollBehavior] is provided to
  /// [Scrollable.scrollBehavior], the [ScrollPhysics] provided by that behavior
  /// will take precedence after [Scrollable.physics].
  ///
  /// The physics can be changed dynamically, but new physics will only take
  /// effect if the _class_ of the provided object changes. Merely constructing
  /// a new instance with a different configuration is insufficient to cause the
  /// physics to be reapplied. (This is because the final object used is
  /// generated dynamically, which can be relatively expensive, and it would be
  /// inefficient to speculatively create this object each frame to see if the
  /// physics should be updated.)
  ///
  /// See also:
  ///
  ///  * [AlwaysScrollableScrollPhysics], which can be used to indicate that the
  ///    scrollable should react to scroll requests (and possible overscroll)
  ///    even if the scrollable's contents fit without scrolling being necessary.
  /// {@endtemplate}
  final ScrollPhysics? physics;

  /// Builds the viewport through which the scrollable content is displayed.
  ///
  /// A typical viewport uses the given [ViewportOffset] to determine which part
  /// of its content is actually visible through the viewport.
  ///
  /// See also:
  ///
  ///  * [Viewport], which is a viewport that displays a list of slivers.
  ///  * [ShrinkWrappingViewport], which is a viewport that displays a list of
  ///    slivers and sizes itself based on the size of the slivers.
  final ViewportBuilder viewportBuilder;

  /// {@template flutter.widgets.Scrollable.incrementCalculator}
  /// An optional function that will be called to calculate the distance to
  /// scroll when the scrollable is asked to scroll via the keyboard using a
  /// [ScrollAction].
  ///
  /// If not supplied, the [Scrollable] will scroll a default amount when a
  /// keyboard navigation key is pressed (e.g. pageUp/pageDown, control-upArrow,
  /// etc.), or otherwise invoked by a [ScrollAction].
  ///
  /// If [incrementCalculator] is null, the default for
  /// [ScrollIncrementType.page] is 80% of the size of the scroll window, and
  /// for [ScrollIncrementType.line], 50 logical pixels.
  /// {@endtemplate}
  final ScrollIncrementCalculator? incrementCalculator;

  /// {@template flutter.widgets.scrollable.excludeFromSemantics}
  /// Whether the scroll actions introduced by this [Scrollable] are exposed
  /// in the semantics tree.
  ///
  /// Text fields with an overflow are usually scrollable to make sure that the
  /// user can get to the beginning/end of the entered text. However, these
  /// scrolling actions are generally not exposed to the semantics layer.
  /// {@endtemplate}
  ///
  /// See also:
  ///
  ///  * [GestureDetector.excludeFromSemantics], which is used to accomplish the
  ///    exclusion.
  final bool excludeFromSemantics;

  /// {@template flutter.widgets.scrollable.hitTestBehavior}
  /// Defines the behavior of gesture detector used in this [Scrollable].
  ///
  /// This defaults to [HitTestBehavior.opaque] which means it prevents targets
  /// behind this [Scrollable] from receiving events.
  /// {@endtemplate}
  ///
  /// See also:
  ///
  ///  * [HitTestBehavior], for an explanation on different behaviors.
  final HitTestBehavior hitTestBehavior;

  /// The number of children that will contribute semantic information.
  ///
  /// The value will be null if the number of children is unknown or unbounded.
  ///
  /// Some subtypes of [ScrollView] can infer this value automatically. For
  /// example [ListView] will use the number of widgets in the child list,
  /// while the [ListView.separated] constructor will use half that amount.
  ///
  /// For [CustomScrollView] and other types which do not receive a builder
  /// or list of widgets, the child count must be explicitly provided.
  ///
  /// See also:
  ///
  ///  * [CustomScrollView], for an explanation of scroll semantics.
  ///  * [SemanticsConfiguration.scrollChildCount], the corresponding semantics property.
  final int? semanticChildCount;

  // TODO(jslavitz): Set the DragStartBehavior default to be start across all widgets.
  /// {@template flutter.widgets.scrollable.dragStartBehavior}
  /// Determines the way that drag start behavior is handled.
  ///
  /// If set to [DragStartBehavior.start], scrolling drag behavior will
  /// begin at the position where the drag gesture won the arena. If set to
  /// [DragStartBehavior.down] it will begin at the position where a down
  /// event is first detected.
  ///
  /// In general, setting this to [DragStartBehavior.start] will make drag
  /// animation smoother and setting it to [DragStartBehavior.down] will make
  /// drag behavior feel slightly more reactive.
  ///
  /// By default, the drag start behavior is [DragStartBehavior.start].
  ///
  /// See also:
  ///
  ///  * [DragGestureRecognizer.dragStartBehavior], which gives an example for
  ///    the different behaviors.
  ///
  /// {@endtemplate}
  final DragStartBehavior dragStartBehavior;

  /// {@template flutter.widgets.scrollable.restorationId}
  /// Restoration ID to save and restore the scroll offset of the scrollable.
  ///
  /// If a restoration id is provided, the scrollable will persist its current
  /// scroll offset and restore it during state restoration.
  ///
  /// The scroll offset is persisted in a [RestorationBucket] claimed from
  /// the surrounding [RestorationScope] using the provided restoration ID.
  ///
  /// See also:
  ///
  ///  * [RestorationManager], which explains how state restoration works in
  ///    Flutter.
  /// {@endtemplate}
  final String? restorationId;

  /// {@template flutter.widgets.scrollable.scrollBehavior}
  /// A [ScrollBehavior] that will be applied to this widget individually.
  ///
  /// Defaults to null, wherein the inherited [ScrollBehavior] is copied and
  /// modified to alter the viewport decoration, like [Scrollbar]s.
  ///
  /// [ScrollBehavior]s also provide [ScrollPhysics]. If an explicit
  /// [ScrollPhysics] is provided in [physics], it will take precedence,
  /// followed by [scrollBehavior], and then the inherited ancestor
  /// [ScrollBehavior].
  /// {@endtemplate}
  final ScrollBehavior? scrollBehavior;

  /// {@macro flutter.material.Material.clipBehavior}
  ///
  /// Defaults to [Clip.hardEdge].
  ///
  /// This is passed to decorators in [ScrollableDetails], and does not directly affect
  /// clipping of the [Scrollable]. This reflects the same [Clip] that is provided
  /// to [ScrollView.clipBehavior] and is supplied to the [Viewport].
  final Clip clipBehavior;

  /// The axis along which the scroll view scrolls.
  ///
  /// Determined by the [axisDirection].
  Axis get axis => axisDirectionToAxis(axisDirection);

  @override
  ScrollableState createState() => ScrollableState();

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(EnumProperty<AxisDirection>('axisDirection', axisDirection));
    properties.add(DiagnosticsProperty<ScrollPhysics>('physics', physics));
    properties.add(StringProperty('restorationId', restorationId));
  }

  /// The state from the closest instance of this class that encloses the given
  /// context, or null if none is found.
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// ScrollableState? scrollable = Scrollable.maybeOf(context);
  /// ```
  ///
  /// Calling this method will create a dependency on the [ScrollableState]
  /// that is returned, if there is one. This is typically the closest
  /// [Scrollable], but may be a more distant ancestor if [axis] is used to
  /// target a specific [Scrollable].
  ///
  /// Using the optional [Axis] is useful when Scrollables are nested and the
  /// target [Scrollable] is not the closest instance. When [axis] is provided,
  /// the nearest enclosing [ScrollableState] in that [Axis] is returned, or
  /// null if there is none.
  ///
  /// This finds the nearest _ancestor_ [Scrollable] of the `context`. This
  /// means that if the `context` is that of a [Scrollable], it will _not_ find
  /// _that_ [Scrollable].
  ///
  /// See also:
  ///
  /// * [Scrollable.of], which is similar to this method, but asserts
  ///   if no [Scrollable] ancestor is found.
  static ScrollableState? maybeOf(BuildContext context, {Axis? axis}) {
    // This is the context that will need to establish the dependency.
    final originalContext = context;
    InheritedElement? element = context.getElementForInheritedWidgetOfExactType<_ScrollableScope>();
    while (element != null) {
      final ScrollableState scrollable = (element.widget as _ScrollableScope).scrollable;
      if (axis == null || axisDirectionToAxis(scrollable.axisDirection) == axis) {
        // Establish the dependency on the correct context.
        originalContext.dependOnInheritedElement(element);
        return scrollable;
      }
      context = scrollable.context;
      element = context.getElementForInheritedWidgetOfExactType<_ScrollableScope>();
    }
    return null;
  }

  /// The state from the closest instance of this class that encloses the given
  /// context.
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// ScrollableState scrollable = Scrollable.of(context);
  /// ```
  ///
  /// Calling this method will create a dependency on the [ScrollableState]
  /// that is returned, if there is one. This is typically the closest
  /// [Scrollable], but may be a more distant ancestor if [axis] is used to
  /// target a specific [Scrollable].
  ///
  /// Using the optional [Axis] is useful when Scrollables are nested and the
  /// target [Scrollable] is not the closest instance. When [axis] is provided,
  /// the nearest enclosing [ScrollableState] in that [Axis] is returned.
  ///
  /// This finds the nearest _ancestor_ [Scrollable] of the `context`. This
  /// means that if the `context` is that of a [Scrollable], it will _not_ find
  /// _that_ [Scrollable].
  ///
  /// If no [Scrollable] ancestor is found, then this method will assert in
  /// debug mode, and throw an exception in release mode.
  ///
  /// See also:
  ///
  /// * [Scrollable.maybeOf], which is similar to this method, but returns null
  ///   if no [Scrollable] ancestor is found.
  static ScrollableState of(BuildContext context, {Axis? axis}) {
    final ScrollableState? scrollableState = maybeOf(context, axis: axis);
    assert(() {
      if (scrollableState == null) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary(
            'Scrollable.of() was called with a context that does not contain a '
            'Scrollable widget.',
          ),
          ErrorDescription(
            'No Scrollable widget ancestor could be found '
            '${axis == null ? '' : 'for the provided Axis: $axis '}'
            'starting from the context that was passed to Scrollable.of(). This '
            'can happen because you are using a widget that looks for a Scrollable '
            'ancestor, but no such ancestor exists.\n'
            'The context used was:\n'
            '  $context',
          ),
          if (axis != null)
            ErrorHint(
              'When specifying an axis, this method will only look for a Scrollable '
              'that matches the given Axis.',
            ),
        ]);
      }
      return true;
    }());
    return scrollableState!;
  }

  /// Provides a heuristic to determine if expensive frame-bound tasks should be
  /// deferred for the [context] at a specific point in time.
  ///
  /// Calling this method does _not_ create a dependency on any other widget.
  /// This also means that the value returned is only good for the point in time
  /// when it is called, and callers will not get updated if the value changes.
  ///
  /// The heuristic used is determined by the [physics] of this [Scrollable]
  /// via [ScrollPhysics.recommendDeferredLoading]. That method is called with
  /// the current [ScrollPosition.activity]'s [ScrollActivity.velocity].
  ///
  /// The optional [Axis] allows targeting of a specific [Scrollable] of that
  /// axis, useful when Scrollables are nested. When [axis] is provided,
  /// [ScrollPosition.recommendDeferredLoading] is called for the nearest
  /// [Scrollable] in that [Axis].
  ///
  /// If there is no [Scrollable] in the widget tree above the [context], this
  /// method returns false.
  static bool recommendDeferredLoadingForContext(BuildContext context, {Axis? axis}) {
    _ScrollableScope? widget = context.getInheritedWidgetOfExactType<_ScrollableScope>();
    while (widget != null) {
      if (axis == null || axisDirectionToAxis(widget.scrollable.axisDirection) == axis) {
        return widget.position.recommendDeferredLoading(context);
      }
      context = widget.scrollable.context;
      widget = context.getInheritedWidgetOfExactType<_ScrollableScope>();
    }
    return false;
  }

  /// Scrolls all scrollables that enclose the given context so as to make the
  /// given context visible.
  ///
  /// If a [Scrollable] enclosing the provided [BuildContext] is a
  /// [TwoDimensionalScrollable], both vertical and horizontal axes will ensure
  /// the target is made visible.
  static Future<void> ensureVisible(
    BuildContext context, {
    double alignment = 0.0,
    Duration duration = Duration.zero,
    Curve curve = Curves.ease,
    ScrollPositionAlignmentPolicy alignmentPolicy = ScrollPositionAlignmentPolicy.explicit,
  }) {
    final futures = <Future<void>>[];

    // The targetRenderObject is used to record the first target renderObject.
    // If there are multiple scrollable widgets nested, the targetRenderObject
    // is made to be as visible as possible to improve the user experience. If
    // the targetRenderObject is already visible, then let the outer
    // renderObject be as visible as possible.
    //
    // Also see https://github.com/flutter/flutter/issues/65100
    RenderObject? targetRenderObject;
    ScrollableState? scrollable = Scrollable.maybeOf(context);
    while (scrollable != null) {
      final List<Future<void>> newFutures;
      (newFutures, scrollable) = scrollable._performEnsureVisible(
        context.findRenderObject()!,
        alignment: alignment,
        duration: duration,
        curve: curve,
        alignmentPolicy: alignmentPolicy,
        targetRenderObject: targetRenderObject,
      );
      futures.addAll(newFutures);

      targetRenderObject ??= context.findRenderObject();
      context = scrollable.context;
      scrollable = Scrollable.maybeOf(context);
    }

    if (futures.isEmpty || duration == Duration.zero) {
      return Future<void>.value();
    }
    if (futures.length == 1) {
      return futures.single;
    }
    return Future.wait<void>(futures).then<void>((List<void> _) => null);
  }
}

// Enable Scrollable.of() to work as if ScrollableState was an inherited widget.
// ScrollableState.build() always rebuilds its _ScrollableScope.
class _ScrollableScope extends InheritedWidget {
  const _ScrollableScope({required this.scrollable, required this.position, required super.child});

  final ScrollableState scrollable;
  final ScrollPosition position;

  @override
  bool updateShouldNotify(_ScrollableScope old) {
    return position != old.position;
  }
}

/// State object for a [Scrollable] widget.
///
/// To manipulate a [Scrollable] widget's scroll position, use the object
/// obtained from the [position] property.
///
/// To be informed of when a [Scrollable] widget is scrolling, use a
/// [NotificationListener] to listen for [ScrollNotification] notifications.
///
/// This class is not intended to be subclassed. To specialize the behavior of a
/// [Scrollable], provide it with a [ScrollPhysics].
class ScrollableState extends State<Scrollable>
    with TickerProviderStateMixin, RestorationMixin
    implements ScrollContext {
  // GETTERS

  /// The manager for this [Scrollable] widget's viewport position.
  ///
  /// To control what kind of [ScrollPosition] is created for a [Scrollable],
  /// provide it with custom [ScrollController] that creates the appropriate
  /// [ScrollPosition] in its [ScrollController.createScrollPosition] method.
  ScrollPosition get position => _position!;
  ScrollPosition? _position;

  /// The resolved [ScrollPhysics] of the [ScrollableState].
  ScrollPhysics? get resolvedPhysics => _physics;
  ScrollPhysics? _physics;

  /// An [Offset] that represents the absolute distance from the origin, or 0,
  /// of the [ScrollPosition] expressed in the associated [Axis].
  ///
  /// Used by [EdgeDraggingAutoScroller] to progress the position forward when a
  /// drag gesture reaches the edge of the [Viewport].
  Offset get deltaToScrollOrigin => switch (axisDirection) {
    AxisDirection.up => Offset(0, -position.pixels),
    AxisDirection.down => Offset(0, position.pixels),
    AxisDirection.left => Offset(-position.pixels, 0),
    AxisDirection.right => Offset(position.pixels, 0),
  };

  ScrollController get _effectiveScrollController =>
      widget.controller ?? _fallbackScrollController!;

  @override
  AxisDirection get axisDirection => widget.axisDirection;

  @override
  TickerProvider get vsync => this;

  @override
  double get devicePixelRatio => _devicePixelRatio;
  late double _devicePixelRatio;

  @override
  BuildContext? get notificationContext => _gestureDetectorKey.currentContext;

  @override
  BuildContext get storageContext => context;

  @override
  String? get restorationId => widget.restorationId;
  final _RestorableScrollOffset _persistedScrollOffset = _RestorableScrollOffset();

  late ScrollBehavior _configuration;
  ScrollController? _fallbackScrollController;
  DeviceGestureSettings? _mediaQueryGestureSettings;

  // Only call this from places that will definitely trigger a rebuild.
  void _updatePosition() {
    _configuration = widget.scrollBehavior ?? ScrollConfiguration.of(context);
    final ScrollPhysics? physicsFromWidget =
        widget.physics ?? widget.scrollBehavior?.getScrollPhysics(context);
    _physics = _configuration.getScrollPhysics(context);
    _physics = physicsFromWidget?.applyTo(_physics) ?? _physics;

    final ScrollPosition? oldPosition = _position;
    if (oldPosition != null) {
      _effectiveScrollController.detach(oldPosition);
      // It's important that we not dispose the old position until after the
      // viewport has had a chance to unregister its listeners from the old
      // position. So, schedule a microtask to do it.
      scheduleMicrotask(oldPosition.dispose);
    }

    _position = _effectiveScrollController.createScrollPosition(_physics!, this, oldPosition);
    assert(_position != null);
    _effectiveScrollController.attach(position);
  }

  @protected
  @override
  void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
    registerForRestoration(_persistedScrollOffset, 'offset');
    assert(_position != null);
    if (_persistedScrollOffset.value != null) {
      position.restoreOffset(_persistedScrollOffset.value!, initialRestore: initialRestore);
    }
  }

  @protected
  @override
  void saveOffset(double offset) {
    assert(debugIsSerializableForRestoration(offset));
    _persistedScrollOffset.value = offset;
    // [saveOffset] is called after a scrolling ends and it is usually not
    // followed by a frame. Therefore, manually flush restoration data.
    ServicesBinding.instance.restorationManager.flushData();
  }

  @protected
  @override
  void initState() {
    if (widget.controller == null) {
      _fallbackScrollController = ScrollController();
    }
    super.initState();
  }

  @protected
  @override
  void didChangeDependencies() {
    _mediaQueryGestureSettings = MediaQuery.maybeGestureSettingsOf(context);
    _devicePixelRatio =
        MediaQuery.maybeDevicePixelRatioOf(context) ?? View.of(context).devicePixelRatio;
    _updatePosition();
    super.didChangeDependencies();
  }

  bool _shouldUpdatePosition(Scrollable oldWidget) {
    if ((widget.scrollBehavior == null) != (oldWidget.scrollBehavior == null)) {
      return true;
    }
    if (widget.scrollBehavior != null &&
        oldWidget.scrollBehavior != null &&
        widget.scrollBehavior!.shouldNotify(oldWidget.scrollBehavior!)) {
      return true;
    }
    ScrollPhysics? newPhysics = widget.physics ?? widget.scrollBehavior?.getScrollPhysics(context);
    ScrollPhysics? oldPhysics =
        oldWidget.physics ?? oldWidget.scrollBehavior?.getScrollPhysics(context);
    do {
      if (newPhysics?.runtimeType != oldPhysics?.runtimeType) {
        return true;
      }
      newPhysics = newPhysics?.parent;
      oldPhysics = oldPhysics?.parent;
    } while (newPhysics != null || oldPhysics != null);

    return widget.controller?.runtimeType != oldWidget.controller?.runtimeType;
  }

  @protected
  @override
  void didUpdateWidget(Scrollable oldWidget) {
    super.didUpdateWidget(oldWidget);

    if (widget.controller != oldWidget.controller) {
      if (oldWidget.controller == null) {
        // The old controller was null, meaning the fallback cannot be null.
        // Dispose of the fallback.
        assert(_fallbackScrollController != null);
        assert(widget.controller != null);
        _fallbackScrollController!.detach(position);
        _fallbackScrollController!.dispose();
        _fallbackScrollController = null;
      } else {
        // The old controller was not null, detach.
        oldWidget.controller?.detach(position);
        if (widget.controller == null) {
          // If the new controller is null, we need to set up the fallback
          // ScrollController.
          _fallbackScrollController = ScrollController();
        }
      }
      // Attach the updated effective scroll controller.
      _effectiveScrollController.attach(position);
    }

    if (_shouldUpdatePosition(oldWidget)) {
      _updatePosition();
    }
  }

  @protected
  @override
  void dispose() {
    if (widget.controller != null) {
      widget.controller!.detach(position);
    } else {
      _fallbackScrollController?.detach(position);
      _fallbackScrollController?.dispose();
    }

    position.dispose();
    _persistedScrollOffset.dispose();
    super.dispose();
  }

  // SEMANTICS

  final GlobalKey _scrollSemanticsKey = GlobalKey();

  @override
  @protected
  void setSemanticsActions(Set<SemanticsAction> actions) {
    if (_gestureDetectorKey.currentState != null) {
      _gestureDetectorKey.currentState!.replaceSemanticsActions(actions);
    }
  }

  // GESTURE RECOGNITION AND POINTER IGNORING

  final GlobalKey<RawGestureDetectorState> _gestureDetectorKey =
      GlobalKey<RawGestureDetectorState>();
  final GlobalKey _ignorePointerKey = GlobalKey();

  // This field is set during layout, and then reused until the next time it is set.
  Map<Type, GestureRecognizerFactory> _gestureRecognizers =
      const <Type, GestureRecognizerFactory>{};
  bool _shouldIgnorePointer = false;

  bool? _lastCanDrag;
  Axis? _lastAxisDirection;

  @override
  @protected
  void setCanDrag(bool value) {
    if (value == _lastCanDrag && (!value || widget.axis == _lastAxisDirection)) {
      return;
    }
    if (!value) {
      _gestureRecognizers = const <Type, GestureRecognizerFactory>{};
      // Cancel the active hold/drag (if any) because the gesture recognizers
      // will soon be disposed by our RawGestureDetector, and we won't be
      // receiving pointer up events to cancel the hold/drag.
      _handleDragCancel();
    } else {
      switch (widget.axis) {
        case Axis.vertical:
          _gestureRecognizers = <Type, GestureRecognizerFactory>{
            VerticalDragGestureRecognizer:
                GestureRecognizerFactoryWithHandlers<VerticalDragGestureRecognizer>(
                  () => VerticalDragGestureRecognizer(supportedDevices: _configuration.dragDevices),
                  (VerticalDragGestureRecognizer instance) {
                    instance
                      ..onDown = _handleDragDown
                      ..onStart = _handleDragStart
                      ..onUpdate = _handleDragUpdate
                      ..onEnd = _handleDragEnd
                      ..onCancel = _handleDragCancel
                      ..minFlingDistance = _physics?.minFlingDistance
                      ..minFlingVelocity = _physics?.minFlingVelocity
                      ..maxFlingVelocity = _physics?.maxFlingVelocity
                      ..velocityTrackerBuilder = _configuration.velocityTrackerBuilder(context)
                      ..dragStartBehavior = widget.dragStartBehavior
                      ..multitouchDragStrategy = _configuration.getMultitouchDragStrategy(context)
                      ..gestureSettings = _mediaQueryGestureSettings
                      ..supportedDevices = _configuration.dragDevices;
                  },
                ),
          };
        case Axis.horizontal:
          _gestureRecognizers = <Type, GestureRecognizerFactory>{
            HorizontalDragGestureRecognizer:
                GestureRecognizerFactoryWithHandlers<HorizontalDragGestureRecognizer>(
                  () =>
                      HorizontalDragGestureRecognizer(supportedDevices: _configuration.dragDevices),
                  (HorizontalDragGestureRecognizer instance) {
                    instance
                      ..onDown = _handleDragDown
                      ..onStart = _handleDragStart
                      ..onUpdate = _handleDragUpdate
                      ..onEnd = _handleDragEnd
                      ..onCancel = _handleDragCancel
                      ..minFlingDistance = _physics?.minFlingDistance
                      ..minFlingVelocity = _physics?.minFlingVelocity
                      ..maxFlingVelocity = _physics?.maxFlingVelocity
                      ..velocityTrackerBuilder = _configuration.velocityTrackerBuilder(context)
                      ..dragStartBehavior = widget.dragStartBehavior
                      ..multitouchDragStrategy = _configuration.getMultitouchDragStrategy(context)
                      ..gestureSettings = _mediaQueryGestureSettings
                      ..supportedDevices = _configuration.dragDevices;
                  },
                ),
          };
      }
    }
    _lastCanDrag = value;
    _lastAxisDirection = widget.axis;
    if (_gestureDetectorKey.currentState != null) {
      _gestureDetectorKey.currentState!.replaceGestureRecognizers(_gestureRecognizers);
    }
  }

  @override
  @protected
  void setIgnorePointer(bool value) {
    if (_shouldIgnorePointer == value) {
      return;
    }
    _shouldIgnorePointer = value;
    if (_ignorePointerKey.currentContext != null) {
      final renderBox =
          _ignorePointerKey.currentContext!.findRenderObject()! as RenderIgnorePointer;
      renderBox.ignoring = _shouldIgnorePointer;
    }
  }

  // TOUCH HANDLERS

  Drag? _drag;
  ScrollHoldController? _hold;

  void _handleDragDown(DragDownDetails details) {
    assert(_drag == null);
    assert(_hold == null);
    _hold = position.hold(_disposeHold);
  }

  void _handleDragStart(DragStartDetails details) {
    // It's possible for _hold to become null between _handleDragDown and
    // _handleDragStart, for example if some user code calls jumpTo or otherwise
    // triggers a new activity to begin.
    assert(_drag == null);
    _drag = position.drag(details, _disposeDrag);
    assert(_drag != null);
    // _hold might be non-null if the scroll position is currently animating.
    if (_hold != null) {
      _disposeHold();
    }
  }

  void _handleDragUpdate(DragUpdateDetails details) {
    // _drag might be null if the drag activity ended and called _disposeDrag.
    assert(_hold == null || _drag == null);
    _drag?.update(details);
  }

  void _handleDragEnd(DragEndDetails details) {
    // _drag might be null if the drag activity ended and called _disposeDrag.
    assert(_hold == null || _drag == null);
    _drag?.end(details);
    assert(_drag == null);
  }

  void _handleDragCancel() {
    if (_gestureDetectorKey.currentContext == null) {
      // The cancel was caused by the GestureDetector getting disposed, which
      // means we will get disposed momentarily as well and shouldn't do
      // any work.
      return;
    }
    // _hold might be null if the drag started.
    // _drag might be null if the drag activity ended and called _disposeDrag.
    assert(_hold == null || _drag == null);
    _hold?.cancel();
    _drag?.cancel();
    assert(_hold == null);
    assert(_drag == null);
  }

  void _disposeHold() {
    _hold = null;
  }

  void _disposeDrag() {
    _drag = null;
  }

  // SCROLL WHEEL

  // Returns the offset that should result from applying [event] to the current
  // position, taking min/max scroll extent into account.
  double _targetScrollOffsetForPointerScroll(double delta) {
    return math.min(
      math.max(position.pixels + delta, position.minScrollExtent),
      position.maxScrollExtent,
    );
  }

  // Returns the delta that should result from applying [event] with axis,
  // direction, and any modifiers specified by the ScrollBehavior taken into
  // account.
  double _pointerSignalEventDelta(PointerScrollEvent event) {
    final Set<LogicalKeyboardKey> pressed = HardwareKeyboard.instance.logicalKeysPressed;
    final bool flipAxes =
        pressed.any(_configuration.pointerAxisModifiers.contains) &&
        // Axes are only flipped for physical mouse wheel input.
        // On some platforms, like web, trackpad input is handled through pointer
        // signals, but should not be included in this axis modifying behavior.
        // This is because on a trackpad, all directional axes are available to
        // the user, while mouse scroll wheels typically are restricted to one
        // axis.
        event.kind == PointerDeviceKind.mouse;

    final Axis axis = flipAxes ? flipAxis(widget.axis) : widget.axis;
    final double delta = switch (axis) {
      Axis.horizontal => event.scrollDelta.dx,
      Axis.vertical => event.scrollDelta.dy,
    };

    return axisDirectionIsReversed(widget.axisDirection) ? -delta : delta;
  }

  void _receivedPointerSignal(PointerSignalEvent event) {
    if (event is PointerScrollEvent && _position != null) {
      if (_physics != null && !_physics!.shouldAcceptUserOffset(position)) {
        // The handler won't use the `event`, so allow the platform to trigger
        // any default native actions.
        event.respond(allowPlatformDefault: true);
        return;
      }
      final double delta = _pointerSignalEventDelta(event);
      final double targetScrollOffset = _targetScrollOffsetForPointerScroll(delta);
      // Only express interest in the event if it would actually result in a scroll.
      if (delta != 0.0 && targetScrollOffset != position.pixels) {
        GestureBinding.instance.pointerSignalResolver.register(event, _handlePointerScroll);
        return;
      }
      // The `event` won't result in a scroll, so allow the platform to trigger
      // any default native actions.
      event.respond(allowPlatformDefault: true);
    } else if (event is PointerScrollInertiaCancelEvent) {
      position.pointerScroll(0);
      // Don't use the pointer signal resolver, all hit-tested scrollables should stop.
    }
  }

  void _handlePointerScroll(PointerEvent event) {
    assert(event is PointerScrollEvent);
    final double delta = _pointerSignalEventDelta(event as PointerScrollEvent);
    final double targetScrollOffset = _targetScrollOffsetForPointerScroll(delta);
    if (delta != 0.0 && targetScrollOffset != position.pixels) {
      position.pointerScroll(delta);
    }
  }

  bool _handleScrollMetricsNotification(ScrollMetricsNotification notification) {
    if (notification.depth == 0) {
      final RenderObject? scrollSemanticsRenderObject = _scrollSemanticsKey.currentContext
          ?.findRenderObject();
      if (scrollSemanticsRenderObject != null) {
        scrollSemanticsRenderObject.markNeedsSemanticsUpdate();
      }
    }
    return false;
  }

  Widget _buildChrome(BuildContext context, Widget child) {
    final details = ScrollableDetails(
      direction: widget.axisDirection,
      controller: _effectiveScrollController,
      decorationClipBehavior: widget.clipBehavior,
    );

    return _configuration.buildScrollbar(
      context,
      _configuration.buildOverscrollIndicator(context, child, details),
      details,
    );
  }

  // DESCRIPTION

  @protected
  @override
  Widget build(BuildContext context) {
    assert(_position != null);
    // _ScrollableScope must be placed above the BuildContext returned by notificationContext
    // so that we can get this ScrollableState by doing the following:
    //
    // ScrollNotification notification;
    // Scrollable.of(notification.context)
    //
    // Since notificationContext is pointing to _gestureDetectorKey.context, _ScrollableScope
    // must be placed above the widget using it: RawGestureDetector
    Widget result = _ScrollableScope(
      scrollable: this,
      position: position,
      child: Listener(
        onPointerSignal: _receivedPointerSignal,
        child: RawGestureDetector(
          key: _gestureDetectorKey,
          gestures: _gestureRecognizers,
          behavior: widget.hitTestBehavior,
          excludeFromSemantics: widget.excludeFromSemantics,
          child: Semantics(
            explicitChildNodes: !widget.excludeFromSemantics,
            child: IgnorePointer(
              key: _ignorePointerKey,
              ignoring: _shouldIgnorePointer,
              child: widget.viewportBuilder(context, position),
            ),
          ),
        ),
      ),
    );

    if (!widget.excludeFromSemantics) {
      result = NotificationListener<ScrollMetricsNotification>(
        onNotification: _handleScrollMetricsNotification,
        child: _ScrollSemantics(
          key: _scrollSemanticsKey,
          position: position,
          allowImplicitScrolling: _physics!.allowImplicitScrolling,
          axis: widget.axis,
          semanticChildCount: widget.semanticChildCount,
          child: result,
        ),
      );
    }

    result = _buildChrome(context, result);

    // Selection is only enabled when there is a parent registrar.
    final SelectionRegistrar? registrar = SelectionContainer.maybeOf(context);
    if (registrar != null) {
      result = _ScrollableSelectionHandler(
        state: this,
        position: position,
        registrar: registrar,
        child: result,
      );
    }

    return result;
  }

  // Returns the Future from calling ensureVisible for the ScrollPosition, as
  // as well as this ScrollableState instance so its context can be used to
  // check for other ancestor Scrollables in executing ensureVisible.
  _EnsureVisibleResults _performEnsureVisible(
    RenderObject object, {
    double alignment = 0.0,
    Duration duration = Duration.zero,
    Curve curve = Curves.ease,
    ScrollPositionAlignmentPolicy alignmentPolicy = ScrollPositionAlignmentPolicy.explicit,
    RenderObject? targetRenderObject,
  }) {
    final Future<void> ensureVisibleFuture = position.ensureVisible(
      object,
      alignment: alignment,
      duration: duration,
      curve: curve,
      alignmentPolicy: alignmentPolicy,
      targetRenderObject: targetRenderObject,
    );
    return (<Future<void>>[ensureVisibleFuture], this);
  }

  @protected
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<ScrollPosition>('position', _position));
    properties.add(DiagnosticsProperty<ScrollPhysics>('effective physics', _physics));
  }
}

/// A widget to handle selection for a scrollable.
///
/// This widget registers itself to the [registrar] and uses
/// [SelectionContainer] to collect selectables from its subtree.
class _ScrollableSelectionHandler extends StatefulWidget {
  const _ScrollableSelectionHandler({
    required this.state,
    required this.position,
    required this.registrar,
    required this.child,
  });

  final ScrollableState state;
  final ScrollPosition position;
  final Widget child;
  final SelectionRegistrar registrar;

  @override
  _ScrollableSelectionHandlerState createState() => _ScrollableSelectionHandlerState();
}

class _ScrollableSelectionHandlerState extends State<_ScrollableSelectionHandler> {
  late _ScrollableSelectionContainerDelegate _selectionDelegate;

  @override
  void initState() {
    super.initState();
    _selectionDelegate = _ScrollableSelectionContainerDelegate(
      state: widget.state,
      position: widget.position,
    );
  }

  @override
  void didUpdateWidget(_ScrollableSelectionHandler oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.position != widget.position) {
      _selectionDelegate.position = widget.position;
    }
  }

  @override
  void dispose() {
    _selectionDelegate.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SelectionContainer(
      registrar: widget.registrar,
      delegate: _selectionDelegate,
      child: widget.child,
    );
  }
}

/// This updater handles the case where the selectables change frequently, and
/// it optimizes toward scrolling updates.
///
/// It keeps track of the drag start offset relative to scroll origin for every
/// selectable. The records are used to determine whether the selection is up to
/// date with the scroll position when it sends the drag update event to a
/// selectable.
class _ScrollableSelectionContainerDelegate extends MultiSelectableSelectionContainerDelegate {
  _ScrollableSelectionContainerDelegate({required this.state, required ScrollPosition position})
    : _position = position,
      _autoScroller = EdgeDraggingAutoScroller(
        state,
        velocityScalar: _kDefaultSelectToScrollVelocityScalar,
      ) {
    _position.addListener(_scheduleLayoutChange);
  }

  // Pointer drag is a single point, it should not have a size.
  static const double _kDefaultDragTargetSize = 0;

  // An eye-balled value for a smooth scrolling speed.
  static const double _kDefaultSelectToScrollVelocityScalar = 30;

  final ScrollableState state;
  final EdgeDraggingAutoScroller _autoScroller;
  bool _scheduledLayoutChange = false;
  Offset? _currentDragStartRelatedToOrigin;
  Offset? _currentDragEndRelatedToOrigin;

  // The scrollable only auto scrolls if the selection starts in the scrollable.
  bool _selectionStartsInScrollable = false;

  ScrollPosition get position => _position;
  ScrollPosition _position;
  set position(ScrollPosition other) {
    if (other == _position) {
      return;
    }
    _position.removeListener(_scheduleLayoutChange);
    _position = other;
    _position.addListener(_scheduleLayoutChange);
  }

  // The layout will only be updated a frame later than position changes.
  // Schedule PostFrameCallback to capture the accurate layout.
  void _scheduleLayoutChange() {
    if (_scheduledLayoutChange) {
      return;
    }
    _scheduledLayoutChange = true;
    SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
      if (!_scheduledLayoutChange) {
        return;
      }
      _scheduledLayoutChange = false;
      layoutDidChange();
    }, debugLabel: 'ScrollableSelectionContainer.layoutDidChange');
  }

  /// Stores the scroll offset when a scrollable receives the last
  /// [SelectionEdgeUpdateEvent].
  ///
  /// The stored scroll offset may be null if a scrollable never receives a
  /// [SelectionEdgeUpdateEvent].
  ///
  /// When a new [SelectionEdgeUpdateEvent] is dispatched to a selectable, this
  /// updater checks the current scroll offset against the one stored in these
  /// records. If the scroll offset is different, it synthesizes an opposite
  /// [SelectionEdgeUpdateEvent] and dispatches the event before dispatching the
  /// new event.
  ///
  /// For example, if a selectable receives an end [SelectionEdgeUpdateEvent]
  /// and its scroll offset in the records is different from the current value,
  /// it synthesizes a start [SelectionEdgeUpdateEvent] and dispatches it before
  /// dispatching the original end [SelectionEdgeUpdateEvent].
  final Map<Selectable, double> _selectableStartEdgeUpdateRecords = <Selectable, double>{};
  final Map<Selectable, double> _selectableEndEdgeUpdateRecords = <Selectable, double>{};

  @override
  void didChangeSelectables() {
    final Set<Selectable> selectableSet = selectables.toSet();
    _selectableStartEdgeUpdateRecords.removeWhere(
      (Selectable key, double value) => !selectableSet.contains(key),
    );
    _selectableEndEdgeUpdateRecords.removeWhere(
      (Selectable key, double value) => !selectableSet.contains(key),
    );
    super.didChangeSelectables();
  }

  @override
  SelectionResult handleClearSelection(ClearSelectionEvent event) {
    _selectableStartEdgeUpdateRecords.clear();
    _selectableEndEdgeUpdateRecords.clear();
    _currentDragStartRelatedToOrigin = null;
    _currentDragEndRelatedToOrigin = null;
    _selectionStartsInScrollable = false;
    return super.handleClearSelection(event);
  }

  @override
  SelectionResult handleSelectionEdgeUpdate(SelectionEdgeUpdateEvent event) {
    if (_currentDragEndRelatedToOrigin == null && _currentDragStartRelatedToOrigin == null) {
      assert(!_selectionStartsInScrollable);
      _selectionStartsInScrollable = _globalPositionInScrollable(event.globalPosition);
    }
    final Offset deltaToOrigin = _getDeltaToScrollOrigin(state);
    if (event.type == SelectionEventType.endEdgeUpdate) {
      _currentDragEndRelatedToOrigin = _inferPositionRelatedToOrigin(event.globalPosition);
      final Offset endOffset = _currentDragEndRelatedToOrigin!.translate(
        -deltaToOrigin.dx,
        -deltaToOrigin.dy,
      );
      event = SelectionEdgeUpdateEvent.forEnd(
        globalPosition: endOffset,
        granularity: event.granularity,
      );
    } else {
      _currentDragStartRelatedToOrigin = _inferPositionRelatedToOrigin(event.globalPosition);
      final Offset startOffset = _currentDragStartRelatedToOrigin!.translate(
        -deltaToOrigin.dx,
        -deltaToOrigin.dy,
      );
      event = SelectionEdgeUpdateEvent.forStart(
        globalPosition: startOffset,
        granularity: event.granularity,
      );
    }
    final SelectionResult result = super.handleSelectionEdgeUpdate(event);

    // Result may be pending if one of the selectable child is also a scrollable.
    // In that case, the parent scrollable needs to wait for the child to finish
    // scrolling.
    if (result == SelectionResult.pending) {
      _autoScroller.stopAutoScroll();
      return result;
    }
    if (_selectionStartsInScrollable) {
      _autoScroller.startAutoScrollIfNecessary(_dragTargetFromEvent(event));
      if (_autoScroller.scrolling) {
        return SelectionResult.pending;
      }
    }
    return result;
  }

  Offset _inferPositionRelatedToOrigin(Offset globalPosition) {
    final box = state.context.findRenderObject()! as RenderBox;
    final Offset localPosition = box.globalToLocal(globalPosition);
    if (!_selectionStartsInScrollable) {
      // If the selection starts outside of the scrollable, selecting across the
      // scrollable boundary will act as selecting the entire content in the
      // scrollable. This logic move the offset to the 0.0 or infinity to cover
      // the entire content if the input position is outside of the scrollable.
      if (localPosition.dy < 0 || localPosition.dx < 0) {
        return box.localToGlobal(Offset.zero);
      }
      if (localPosition.dy > box.size.height || localPosition.dx > box.size.width) {
        return Offset.infinite;
      }
    }
    final Offset deltaToOrigin = _getDeltaToScrollOrigin(state);
    return box.localToGlobal(localPosition.translate(deltaToOrigin.dx, deltaToOrigin.dy));
  }

  /// Infers the [_currentDragStartRelatedToOrigin] and
  /// [_currentDragEndRelatedToOrigin] from the geometry.
  ///
  /// This method is called after a select word and select all event where the
  /// selection is triggered by none drag events. The
  /// [_currentDragStartRelatedToOrigin] and [_currentDragEndRelatedToOrigin]
  /// are essential to handle future [SelectionEdgeUpdateEvent]s.
  void _updateDragLocationsFromGeometries({
    bool forceUpdateStart = true,
    bool forceUpdateEnd = true,
  }) {
    final Offset deltaToOrigin = _getDeltaToScrollOrigin(state);
    final box = state.context.findRenderObject()! as RenderBox;
    final Matrix4 transform = box.getTransformTo(null);
    if (currentSelectionStartIndex != -1 &&
        (_currentDragStartRelatedToOrigin == null || forceUpdateStart)) {
      final SelectionGeometry geometry = selectables[currentSelectionStartIndex].value;
      assert(geometry.hasSelection);
      final SelectionPoint start = geometry.startSelectionPoint!;
      final Matrix4 childTransform = selectables[currentSelectionStartIndex].getTransformTo(box);
      final Offset localDragStart = MatrixUtils.transformPoint(
        childTransform,
        start.localPosition + Offset(0, -start.lineHeight / 2),
      );
      _currentDragStartRelatedToOrigin = MatrixUtils.transformPoint(
        transform,
        localDragStart + deltaToOrigin,
      );
    }
    if (currentSelectionEndIndex != -1 &&
        (_currentDragEndRelatedToOrigin == null || forceUpdateEnd)) {
      final SelectionGeometry geometry = selectables[currentSelectionEndIndex].value;
      assert(geometry.hasSelection);
      final SelectionPoint end = geometry.endSelectionPoint!;
      final Matrix4 childTransform = selectables[currentSelectionEndIndex].getTransformTo(box);
      final Offset localDragEnd = MatrixUtils.transformPoint(
        childTransform,
        end.localPosition + Offset(0, -end.lineHeight / 2),
      );
      _currentDragEndRelatedToOrigin = MatrixUtils.transformPoint(
        transform,
        localDragEnd + deltaToOrigin,
      );
    }
  }

  @override
  SelectionResult handleSelectAll(SelectAllSelectionEvent event) {
    assert(!_selectionStartsInScrollable);
    final SelectionResult result = super.handleSelectAll(event);
    assert((currentSelectionStartIndex == -1) == (currentSelectionEndIndex == -1));
    if (currentSelectionStartIndex != -1) {
      _updateDragLocationsFromGeometries();
    }
    return result;
  }

  @override
  SelectionResult handleSelectWord(SelectWordSelectionEvent event) {
    _selectionStartsInScrollable = _globalPositionInScrollable(event.globalPosition);
    final SelectionResult result = super.handleSelectWord(event);
    _updateDragLocationsFromGeometries();
    return result;
  }

  @override
  SelectionResult handleGranularlyExtendSelection(GranularlyExtendSelectionEvent event) {
    final SelectionResult result = super.handleGranularlyExtendSelection(event);
    // The selection geometry may not have the accurate offset for the edges
    // that are outside of the viewport whose transform may not be valid. Only
    // the edge this event is updating is sure to be accurate.
    _updateDragLocationsFromGeometries(forceUpdateStart: !event.isEnd, forceUpdateEnd: event.isEnd);
    if (_selectionStartsInScrollable) {
      _jumpToEdge(event.isEnd);
    }
    return result;
  }

  @override
  SelectionResult handleDirectionallyExtendSelection(DirectionallyExtendSelectionEvent event) {
    final SelectionResult result = super.handleDirectionallyExtendSelection(event);
    // The selection geometry may not have the accurate offset for the edges
    // that are outside of the viewport whose transform may not be valid. Only
    // the edge this event is updating is sure to be accurate.
    _updateDragLocationsFromGeometries(forceUpdateStart: !event.isEnd, forceUpdateEnd: event.isEnd);
    if (_selectionStartsInScrollable) {
      _jumpToEdge(event.isEnd);
    }
    return result;
  }

  void _jumpToEdge(bool isExtent) {
    final Selectable selectable;
    final double? lineHeight;
    final SelectionPoint? edge;
    if (isExtent) {
      selectable = selectables[currentSelectionEndIndex];
      edge = selectable.value.endSelectionPoint;
      lineHeight = selectable.value.endSelectionPoint!.lineHeight;
    } else {
      selectable = selectables[currentSelectionStartIndex];
      edge = selectable.value.startSelectionPoint;
      lineHeight = selectable.value.startSelectionPoint?.lineHeight;
    }
    if (lineHeight == null || edge == null) {
      return;
    }
    final scrollableBox = state.context.findRenderObject()! as RenderBox;
    final Matrix4 transform = selectable.getTransformTo(scrollableBox);
    final Offset edgeOffsetInScrollableCoordinates = MatrixUtils.transformPoint(
      transform,
      edge.localPosition,
    );
    final scrollableRect = Rect.fromLTRB(0, 0, scrollableBox.size.width, scrollableBox.size.height);
    switch (state.axisDirection) {
      case AxisDirection.up:
        final double edgeBottom = edgeOffsetInScrollableCoordinates.dy;
        final double edgeTop = edgeOffsetInScrollableCoordinates.dy - lineHeight;
        if (edgeBottom >= scrollableRect.bottom && edgeTop <= scrollableRect.top) {
          return;
        }
        if (edgeBottom > scrollableRect.bottom) {
          position.jumpTo(position.pixels + scrollableRect.bottom - edgeBottom);
          return;
        }
        if (edgeTop < scrollableRect.top) {
          position.jumpTo(position.pixels + scrollableRect.top - edgeTop);
        }
        return;
      case AxisDirection.right:
        final double edge = edgeOffsetInScrollableCoordinates.dx;
        if (edge >= scrollableRect.right && edge <= scrollableRect.left) {
          return;
        }
        if (edge > scrollableRect.right) {
          position.jumpTo(position.pixels + edge - scrollableRect.right);
          return;
        }
        if (edge < scrollableRect.left) {
          position.jumpTo(position.pixels + edge - scrollableRect.left);
        }
        return;
      case AxisDirection.down:
        final double edgeBottom = edgeOffsetInScrollableCoordinates.dy;
        final double edgeTop = edgeOffsetInScrollableCoordinates.dy - lineHeight;
        if (edgeBottom >= scrollableRect.bottom && edgeTop <= scrollableRect.top) {
          return;
        }
        if (edgeBottom > scrollableRect.bottom) {
          position.jumpTo(position.pixels + edgeBottom - scrollableRect.bottom);
          return;
        }
        if (edgeTop < scrollableRect.top) {
          position.jumpTo(position.pixels + edgeTop - scrollableRect.top);
        }
        return;
      case AxisDirection.left:
        final double edge = edgeOffsetInScrollableCoordinates.dx;
        if (edge >= scrollableRect.right && edge <= scrollableRect.left) {
          return;
        }
        if (edge > scrollableRect.right) {
          position.jumpTo(position.pixels + scrollableRect.right - edge);
          return;
        }
        if (edge < scrollableRect.left) {
          position.jumpTo(position.pixels + scrollableRect.left - edge);
        }
        return;
    }
  }

  bool _globalPositionInScrollable(Offset globalPosition) {
    final box = state.context.findRenderObject()! as RenderBox;
    final Offset localPosition = box.globalToLocal(globalPosition);
    final rect = Rect.fromLTWH(0, 0, box.size.width, box.size.height);
    return rect.contains(localPosition);
  }

  Rect _dragTargetFromEvent(SelectionEdgeUpdateEvent event) {
    return Rect.fromCenter(
      center: event.globalPosition,
      width: _kDefaultDragTargetSize,
      height: _kDefaultDragTargetSize,
    );
  }

  @override
  SelectionResult dispatchSelectionEventToChild(Selectable selectable, SelectionEvent event) {
    switch (event.type) {
      case SelectionEventType.startEdgeUpdate:
        _selectableStartEdgeUpdateRecords[selectable] = state.position.pixels;
        ensureChildUpdated(selectable);
      case SelectionEventType.endEdgeUpdate:
        _selectableEndEdgeUpdateRecords[selectable] = state.position.pixels;
        ensureChildUpdated(selectable);
      case SelectionEventType.granularlyExtendSelection:
      case SelectionEventType.directionallyExtendSelection:
        ensureChildUpdated(selectable);
        _selectableStartEdgeUpdateRecords[selectable] = state.position.pixels;
        _selectableEndEdgeUpdateRecords[selectable] = state.position.pixels;
      case SelectionEventType.clear:
        _selectableEndEdgeUpdateRecords.remove(selectable);
        _selectableStartEdgeUpdateRecords.remove(selectable);
      case SelectionEventType.selectAll:
      case SelectionEventType.selectWord:
      case SelectionEventType.selectParagraph:
        _selectableEndEdgeUpdateRecords[selectable] = state.position.pixels;
        _selectableStartEdgeUpdateRecords[selectable] = state.position.pixels;
    }
    return super.dispatchSelectionEventToChild(selectable, event);
  }

  @override
  void ensureChildUpdated(Selectable selectable) {
    final double newRecord = state.position.pixels;
    final double? previousStartRecord = _selectableStartEdgeUpdateRecords[selectable];
    if (_currentDragStartRelatedToOrigin != null &&
        (previousStartRecord == null ||
            (newRecord - previousStartRecord).abs() > precisionErrorTolerance)) {
      // Make sure the selectable has up to date events.
      final Offset deltaToOrigin = _getDeltaToScrollOrigin(state);
      final Offset startOffset = _currentDragStartRelatedToOrigin!.translate(
        -deltaToOrigin.dx,
        -deltaToOrigin.dy,
      );
      selectable.dispatchSelectionEvent(
        SelectionEdgeUpdateEvent.forStart(globalPosition: startOffset),
      );
      // Make sure we track that we have synthesized a start event for this selectable,
      // so we don't synthesize events unnecessarily.
      _selectableStartEdgeUpdateRecords[selectable] = state.position.pixels;
    }
    final double? previousEndRecord = _selectableEndEdgeUpdateRecords[selectable];
    if (_currentDragEndRelatedToOrigin != null &&
        (previousEndRecord == null ||
            (newRecord - previousEndRecord).abs() > precisionErrorTolerance)) {
      // Make sure the selectable has up to date events.
      final Offset deltaToOrigin = _getDeltaToScrollOrigin(state);
      final Offset endOffset = _currentDragEndRelatedToOrigin!.translate(
        -deltaToOrigin.dx,
        -deltaToOrigin.dy,
      );
      selectable.dispatchSelectionEvent(SelectionEdgeUpdateEvent.forEnd(globalPosition: endOffset));
      // Make sure we track that we have synthesized an end event for this selectable,
      // so we don't synthesize events unnecessarily.
      _selectableEndEdgeUpdateRecords[selectable] = state.position.pixels;
    }
  }

  @override
  void dispose() {
    _selectableStartEdgeUpdateRecords.clear();
    _selectableEndEdgeUpdateRecords.clear();
    _scheduledLayoutChange = false;
    _autoScroller.stopAutoScroll();
    super.dispose();
  }
}

Offset _getDeltaToScrollOrigin(ScrollableState scrollableState) {
  return switch (scrollableState.axisDirection) {
    AxisDirection.up => Offset(0, -scrollableState.position.pixels),
    AxisDirection.down => Offset(0, scrollableState.position.pixels),
    AxisDirection.left => Offset(-scrollableState.position.pixels, 0),
    AxisDirection.right => Offset(scrollableState.position.pixels, 0),
  };
}

/// With [_ScrollSemantics] certain child [SemanticsNode]s can be
/// excluded from the scrollable area for semantics purposes.
///
/// Nodes, that are to be excluded, have to be tagged with
/// [RenderViewport.excludeFromScrolling] and the [RenderAbstractViewport] in
/// use has to add the [RenderViewport.useTwoPaneSemantics] tag to its
/// [SemanticsConfiguration] by overriding
/// [RenderObject.describeSemanticsConfiguration].
///
/// If the tag [RenderViewport.useTwoPaneSemantics] is present on the viewport,
/// two semantics nodes will be used to represent the [Scrollable]: The outer
/// node will contain all children, that are excluded from scrolling. The inner
/// node, which is annotated with the scrolling actions, will house the
/// scrollable children.
class _ScrollSemantics extends SingleChildRenderObjectWidget {
  const _ScrollSemantics({
    super.key,
    required this.position,
    required this.allowImplicitScrolling,
    required this.axis,
    required this.semanticChildCount,
    super.child,
  }) : assert(semanticChildCount == null || semanticChildCount >= 0);

  final ScrollPosition position;
  final bool allowImplicitScrolling;
  final int? semanticChildCount;
  final Axis axis;

  @override
  _RenderScrollSemantics createRenderObject(BuildContext context) {
    return _RenderScrollSemantics(
      position: position,
      allowImplicitScrolling: allowImplicitScrolling,
      semanticChildCount: semanticChildCount,
      axis: axis,
    );
  }

  @override
  void updateRenderObject(BuildContext context, _RenderScrollSemantics renderObject) {
    renderObject
      ..allowImplicitScrolling = allowImplicitScrolling
      ..axis = axis
      ..position = position
      ..semanticChildCount = semanticChildCount;
  }
}

class _RenderScrollSemantics extends RenderProxyBox {
  _RenderScrollSemantics({
    required ScrollPosition position,
    required bool allowImplicitScrolling,
    required this.axis,
    required int? semanticChildCount,
    RenderBox? child,
  }) : _position = position,
       _allowImplicitScrolling = allowImplicitScrolling,
       _semanticChildCount = semanticChildCount,
       super(child) {
    position.addListener(markNeedsSemanticsUpdate);
  }

  /// Whether this render object is excluded from the semantic tree.
  ScrollPosition get position => _position;
  ScrollPosition _position;
  set position(ScrollPosition value) {
    if (value == _position) {
      return;
    }
    _position.removeListener(markNeedsSemanticsUpdate);
    _position = value;
    _position.addListener(markNeedsSemanticsUpdate);
    markNeedsSemanticsUpdate();
  }

  /// Whether this node can be scrolled implicitly.
  bool get allowImplicitScrolling => _allowImplicitScrolling;
  bool _allowImplicitScrolling;
  set allowImplicitScrolling(bool value) {
    if (value == _allowImplicitScrolling) {
      return;
    }
    _allowImplicitScrolling = value;
    markNeedsSemanticsUpdate();
  }

  Axis axis;

  int? get semanticChildCount => _semanticChildCount;
  int? _semanticChildCount;
  set semanticChildCount(int? value) {
    if (value == semanticChildCount) {
      return;
    }
    _semanticChildCount = value;
    markNeedsSemanticsUpdate();
  }

  void _onScrollToOffset(Offset targetOffset) {
    final double offset = switch (axis) {
      Axis.horizontal => targetOffset.dx,
      Axis.vertical => targetOffset.dy,
    };
    _position.jumpTo(offset);
  }

  @override
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    super.describeSemanticsConfiguration(config);
    config.isSemanticBoundary = true;
    if (position.haveDimensions) {
      config
        ..hasImplicitScrolling = allowImplicitScrolling
        ..scrollPosition = _position.pixels
        ..scrollExtentMax = _position.maxScrollExtent
        ..scrollExtentMin = _position.minScrollExtent
        ..scrollChildCount = semanticChildCount;
      if (position.maxScrollExtent > position.minScrollExtent && allowImplicitScrolling) {
        config.onScrollToOffset = _onScrollToOffset;
      }
    }
  }

  SemanticsNode? _innerNode;

  @override
  void assembleSemanticsNode(
    SemanticsNode node,
    SemanticsConfiguration config,
    Iterable<SemanticsNode> children,
  ) {
    if (children.isEmpty || !children.first.isTagged(RenderViewport.useTwoPaneSemantics)) {
      _innerNode = null;
      super.assembleSemanticsNode(node, config, children);
      return;
    }

    (_innerNode ??= SemanticsNode(showOnScreen: showOnScreen)).rect = node.rect;

    int? firstVisibleIndex;
    final excluded = <SemanticsNode>[_innerNode!];
    final included = <SemanticsNode>[];
    for (final child in children) {
      assert(child.isTagged(RenderViewport.useTwoPaneSemantics));
      if (child.isTagged(RenderViewport.excludeFromScrolling)) {
        excluded.add(child);
      } else {
        if (!child.flagsCollection.isHidden) {
          firstVisibleIndex ??= child.indexInParent;
        }
        included.add(child);
      }
    }
    config.scrollIndex = firstVisibleIndex;
    node.updateWith(config: null, childrenInInversePaintOrder: excluded);
    _innerNode!.updateWith(config: config, childrenInInversePaintOrder: included);
  }

  @override
  void clearSemantics() {
    super.clearSemantics();
    _innerNode = null;
  }
}

// Not using a RestorableDouble because we want to allow null values and override
// [enabled].
class _RestorableScrollOffset extends RestorableValue<double?> {
  @override
  double? createDefaultValue() => null;

  @override
  void didUpdateValue(double? oldValue) {
    notifyListeners();
  }

  @override
  double fromPrimitives(Object? data) {
    return data! as double;
  }

  @override
  Object? toPrimitives() {
    return value;
  }

  @override
  bool get enabled => value != null;
}

// 2D SCROLLING

/// Specifies how to configure the [DragGestureRecognizer]s of a
/// [TwoDimensionalScrollable].
// TODO(Piinks): Add sample code, https://github.com/flutter/flutter/issues/126298
enum DiagonalDragBehavior {
  /// This behavior will not allow for any diagonal scrolling.
  ///
  /// Drag gestures in one direction or the other will lock the input axis until
  /// the gesture is released.
  none,

  /// This behavior will only allow diagonal scrolling on a weighted
  /// scale per gesture event.
  ///
  /// This means that after initially evaluating the drag gesture, the weighted
  /// evaluation (based on [kTouchSlop]) stands until the gesture is released.
  weightedEvent,

  /// This behavior will only allow diagonal scrolling on a weighted
  /// scale that is evaluated throughout a gesture event.
  ///
  /// This means that during each update to the drag gesture, the scrolling
  /// axis will be allowed to scroll diagonally if it exceeds the
  /// [kTouchSlop].
  weightedContinuous,

  /// This behavior allows free movement in any and all directions when
  /// dragging.
  free,
}

/// A widget that manages scrolling in both the vertical and horizontal
/// dimensions and informs the [TwoDimensionalViewport] through which the
/// content is viewed.
///
/// [TwoDimensionalScrollable] implements the interaction model for a scrollable
/// widget in both the vertical and horizontal axes, including gesture
/// recognition, but does not have an opinion about how the
/// [TwoDimensionalViewport], which actually displays the children, is
/// constructed.
///
/// It's rare to construct a [TwoDimensionalScrollable] directly. Instead,
/// consider subclassing [TwoDimensionalScrollView], which combines scrolling,
/// viewporting, and a layout model in both dimensions.
///
/// See also:
///
///  * [TwoDimensionalScrollView], an abstract base class for displaying a
///    scrolling array of children in both directions.
///  * [TwoDimensionalViewport], which can be used to customize the child layout
///    model.
class TwoDimensionalScrollable extends StatefulWidget {
  /// Creates a widget that scrolls in two dimensions.
  ///
  /// The [horizontalDetails], [verticalDetails], and [viewportBuilder] must not
  /// be null.
  const TwoDimensionalScrollable({
    super.key,
    required this.horizontalDetails,
    required this.verticalDetails,
    required this.viewportBuilder,
    this.incrementCalculator,
    this.restorationId,
    this.excludeFromSemantics = false,
    this.diagonalDragBehavior = DiagonalDragBehavior.none,
    this.dragStartBehavior = DragStartBehavior.start,
    this.hitTestBehavior = HitTestBehavior.opaque,
  });

  /// How scrolling gestures should lock to one axis, or allow free movement
  /// in both axes.
  final DiagonalDragBehavior diagonalDragBehavior;

  /// The configuration of the horizontal [Scrollable].
  ///
  /// These [ScrollableDetails] can be used to set the [AxisDirection],
  /// [ScrollController], [ScrollPhysics] and more for the horizontal axis.
  final ScrollableDetails horizontalDetails;

  /// The configuration of the vertical [Scrollable].
  ///
  /// These [ScrollableDetails] can be used to set the [AxisDirection],
  /// [ScrollController], [ScrollPhysics] and more for the vertical axis.
  final ScrollableDetails verticalDetails;

  /// Builds the viewport through which the scrollable content is displayed.
  ///
  /// A [TwoDimensionalViewport] uses two given [ViewportOffset]s to determine
  /// which part of its content is actually visible through the viewport.
  ///
  /// See also:
  ///
  ///  * [TwoDimensionalViewport], which is a viewport that displays a span of
  ///    widgets in both dimensions.
  final TwoDimensionalViewportBuilder viewportBuilder;

  /// {@macro flutter.widgets.Scrollable.incrementCalculator}
  ///
  /// This value applies in both axes.
  final ScrollIncrementCalculator? incrementCalculator;

  /// {@macro flutter.widgets.scrollable.restorationId}
  ///
  /// Internally, the [TwoDimensionalScrollable] will introduce a
  /// [RestorationScope] that will be assigned this value. The two [Scrollable]s
  /// within will then be given unique IDs within this scope.
  final String? restorationId;

  /// {@macro flutter.widgets.scrollable.excludeFromSemantics}
  ///
  /// This value applies to both axes.
  final bool excludeFromSemantics;

  /// {@macro flutter.widgets.scrollable.hitTestBehavior}
  ///
  /// This value applies to both axes.
  final HitTestBehavior hitTestBehavior;

  /// {@macro flutter.widgets.scrollable.dragStartBehavior}
  ///
  /// This value applies in both axes.
  final DragStartBehavior dragStartBehavior;

  @override
  State<TwoDimensionalScrollable> createState() => TwoDimensionalScrollableState();

  /// The state from the closest instance of this class that encloses the given
  /// context, or null if none is found.
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// TwoDimensionalScrollableState? scrollable = TwoDimensionalScrollable.maybeOf(context);
  /// ```
  ///
  /// Calling this method will create a dependency on the closest
  /// [TwoDimensionalScrollable] in the [context]. The internal [Scrollable]s
  /// can be accessed through [TwoDimensionalScrollableState.verticalScrollable]
  /// and [TwoDimensionalScrollableState.horizontalScrollable].
  ///
  /// Alternatively, [Scrollable.maybeOf] can be used by providing the desired
  /// [Axis] to the `axis` parameter.
  ///
  /// See also:
  ///
  /// * [TwoDimensionalScrollable.of], which is similar to this method, but
  ///   asserts if no [Scrollable] ancestor is found.
  static TwoDimensionalScrollableState? maybeOf(BuildContext context) {
    final _TwoDimensionalScrollableScope? widget = context
        .dependOnInheritedWidgetOfExactType<_TwoDimensionalScrollableScope>();
    return widget?.twoDimensionalScrollable;
  }

  /// The state from the closest instance of this class that encloses the given
  /// context.
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// TwoDimensionalScrollableState scrollable = TwoDimensionalScrollable.of(context);
  /// ```
  ///
  /// Calling this method will create a dependency on the closest
  /// [TwoDimensionalScrollable] in the [context]. The internal [Scrollable]s
  /// can be accessed through [TwoDimensionalScrollableState.verticalScrollable]
  /// and [TwoDimensionalScrollableState.horizontalScrollable].
  ///
  /// If no [TwoDimensionalScrollable] ancestor is found, then this method will
  /// assert in debug mode, and throw an exception in release mode.
  ///
  /// Alternatively, [Scrollable.of] can be used by providing the desired [Axis]
  /// to the `axis` parameter.
  ///
  /// See also:
  ///
  /// * [TwoDimensionalScrollable.maybeOf], which is similar to this method,
  ///   but returns null if no [TwoDimensionalScrollable] ancestor is found.
  static TwoDimensionalScrollableState of(BuildContext context) {
    final TwoDimensionalScrollableState? scrollableState = maybeOf(context);
    assert(() {
      if (scrollableState == null) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary(
            'TwoDimensionalScrollable.of() was called with a context that does '
            'not contain a TwoDimensionalScrollable widget.\n',
          ),
          ErrorDescription(
            'No TwoDimensionalScrollable widget ancestor could be found starting '
            'from the context that was passed to TwoDimensionalScrollable.of(). '
            'This can happen because you are using a widget that looks for a '
            'TwoDimensionalScrollable ancestor, but no such ancestor exists.\n'
            'The context used was:\n'
            '  $context',
          ),
        ]);
      }
      return true;
    }());
    return scrollableState!;
  }
}

/// State object for a [TwoDimensionalScrollable] widget.
///
/// To manipulate one of the internal [Scrollable] widget's scroll position, use
/// the object obtained from the [verticalScrollable] or [horizontalScrollable]
/// property.
///
/// To be informed of when a [TwoDimensionalScrollable] widget is scrolling,
/// use a [NotificationListener] to listen for [ScrollNotification]s.
/// Both axes will have the same viewport depth since there is only one
/// viewport, and so should be differentiated by the [Axis] of the
/// [ScrollMetrics] provided by the notification.
class TwoDimensionalScrollableState extends State<TwoDimensionalScrollable> {
  ScrollController? _verticalFallbackController;
  ScrollController? _horizontalFallbackController;
  final GlobalKey<ScrollableState> _verticalOuterScrollableKey = GlobalKey<ScrollableState>();
  final GlobalKey<ScrollableState> _horizontalInnerScrollableKey = GlobalKey<ScrollableState>();

  /// The [ScrollableState] of the vertical axis.
  ///
  /// Accessible by calling [TwoDimensionalScrollable.of].
  ///
  /// Alternatively, [Scrollable.of] can be used by providing [Axis.vertical]
  /// to the `axis` parameter.
  ScrollableState get verticalScrollable {
    assert(_verticalOuterScrollableKey.currentState != null);
    return _verticalOuterScrollableKey.currentState!;
  }

  /// The [ScrollableState] of the horizontal axis.
  ///
  /// Accessible by calling [TwoDimensionalScrollable.of].
  ///
  /// Alternatively, [Scrollable.of] can be used by providing [Axis.horizontal]
  /// to the `axis` parameter.
  ScrollableState get horizontalScrollable {
    assert(_horizontalInnerScrollableKey.currentState != null);
    return _horizontalInnerScrollableKey.currentState!;
  }

  @protected
  @override
  void initState() {
    if (widget.verticalDetails.controller == null) {
      _verticalFallbackController = ScrollController();
    }
    if (widget.horizontalDetails.controller == null) {
      _horizontalFallbackController = ScrollController();
    }
    super.initState();
  }

  @protected
  @override
  void didUpdateWidget(TwoDimensionalScrollable oldWidget) {
    super.didUpdateWidget(oldWidget);
    // Handle changes in the provided/fallback scroll controllers

    // Vertical
    if (oldWidget.verticalDetails.controller != widget.verticalDetails.controller) {
      if (oldWidget.verticalDetails.controller == null) {
        // The old controller was null, meaning the fallback cannot be null.
        // Dispose of the fallback.
        assert(_verticalFallbackController != null);
        assert(widget.verticalDetails.controller != null);
        _verticalFallbackController!.dispose();
        _verticalFallbackController = null;
      } else if (widget.verticalDetails.controller == null) {
        // If the new controller is null, we need to set up the fallback
        // ScrollController.
        assert(_verticalFallbackController == null);
        _verticalFallbackController = ScrollController();
      }
    }

    // Horizontal
    if (oldWidget.horizontalDetails.controller != widget.horizontalDetails.controller) {
      if (oldWidget.horizontalDetails.controller == null) {
        // The old controller was null, meaning the fallback cannot be null.
        // Dispose of the fallback.
        assert(_horizontalFallbackController != null);
        assert(widget.horizontalDetails.controller != null);
        _horizontalFallbackController!.dispose();
        _horizontalFallbackController = null;
      } else if (widget.horizontalDetails.controller == null) {
        // If the new controller is null, we need to set up the fallback
        // ScrollController.
        assert(_horizontalFallbackController == null);
        _horizontalFallbackController = ScrollController();
      }
    }
  }

  @protected
  @override
  Widget build(BuildContext context) {
    assert(
      axisDirectionToAxis(widget.verticalDetails.direction) == Axis.vertical,
      'TwoDimensionalScrollable.verticalDetails are not Axis.vertical.',
    );
    assert(
      axisDirectionToAxis(widget.horizontalDetails.direction) == Axis.horizontal,
      'TwoDimensionalScrollable.horizontalDetails are not Axis.horizontal.',
    );

    final Widget result = RestorationScope(
      restorationId: widget.restorationId,
      child: _VerticalOuterDimension(
        key: _verticalOuterScrollableKey,
        // For gesture forwarding
        horizontalKey: _horizontalInnerScrollableKey,
        axisDirection: widget.verticalDetails.direction,
        controller: widget.verticalDetails.controller ?? _verticalFallbackController!,
        physics: widget.verticalDetails.physics,
        clipBehavior:
            widget.verticalDetails.clipBehavior ??
            widget.verticalDetails.decorationClipBehavior ??
            Clip.hardEdge,
        incrementCalculator: widget.incrementCalculator,
        excludeFromSemantics: widget.excludeFromSemantics,
        restorationId: 'OuterVerticalTwoDimensionalScrollable',
        dragStartBehavior: widget.dragStartBehavior,
        diagonalDragBehavior: widget.diagonalDragBehavior,
        hitTestBehavior: widget.hitTestBehavior,
        viewportBuilder: (BuildContext context, ViewportOffset verticalOffset) {
          return _HorizontalInnerDimension(
            key: _horizontalInnerScrollableKey,
            verticalOuterKey: _verticalOuterScrollableKey,
            axisDirection: widget.horizontalDetails.direction,
            controller: widget.horizontalDetails.controller ?? _horizontalFallbackController!,
            physics: widget.horizontalDetails.physics,
            clipBehavior:
                widget.horizontalDetails.clipBehavior ??
                widget.horizontalDetails.decorationClipBehavior ??
                Clip.hardEdge,
            incrementCalculator: widget.incrementCalculator,
            excludeFromSemantics: widget.excludeFromSemantics,
            restorationId: 'InnerHorizontalTwoDimensionalScrollable',
            dragStartBehavior: widget.dragStartBehavior,
            diagonalDragBehavior: widget.diagonalDragBehavior,
            hitTestBehavior: widget.hitTestBehavior,
            viewportBuilder: (BuildContext context, ViewportOffset horizontalOffset) {
              return widget.viewportBuilder(context, verticalOffset, horizontalOffset);
            },
          );
        },
      ),
    );

    // TODO(Piinks): Build scrollbars for 2 dimensions instead of 1,
    //  https://github.com/flutter/flutter/issues/122348

    return _TwoDimensionalScrollableScope(twoDimensionalScrollable: this, child: result);
  }

  @protected
  @override
  void dispose() {
    _verticalFallbackController?.dispose();
    _horizontalFallbackController?.dispose();
    super.dispose();
  }
}

// Enable TwoDimensionalScrollable.of() to work as if
// TwoDimensionalScrollableState was an inherited widget.
// TwoDimensionalScrollableState.build() always rebuilds its
// _TwoDimensionalScrollableScope.
class _TwoDimensionalScrollableScope extends InheritedWidget {
  const _TwoDimensionalScrollableScope({
    required this.twoDimensionalScrollable,
    required super.child,
  });

  final TwoDimensionalScrollableState twoDimensionalScrollable;

  @override
  bool updateShouldNotify(_TwoDimensionalScrollableScope old) => false;
}

// Vertical outer scrollable of 2D scrolling
class _VerticalOuterDimension extends Scrollable {
  const _VerticalOuterDimension({
    super.key,
    required this.horizontalKey,
    required super.viewportBuilder,
    required super.axisDirection,
    super.controller,
    super.physics,
    super.clipBehavior,
    super.incrementCalculator,
    super.excludeFromSemantics,
    super.dragStartBehavior,
    super.restorationId,
    super.hitTestBehavior,
    this.diagonalDragBehavior = DiagonalDragBehavior.none,
  }) : assert(axisDirection == AxisDirection.up || axisDirection == AxisDirection.down);

  final DiagonalDragBehavior diagonalDragBehavior;
  final GlobalKey<ScrollableState> horizontalKey;

  @override
  _VerticalOuterDimensionState createState() => _VerticalOuterDimensionState();
}

class _VerticalOuterDimensionState extends ScrollableState {
  DiagonalDragBehavior get diagonalDragBehavior =>
      (widget as _VerticalOuterDimension).diagonalDragBehavior;
  ScrollableState get horizontalScrollable =>
      (widget as _VerticalOuterDimension).horizontalKey.currentState!;

  Axis? lockedAxis;
  Offset? lastDragOffset;

  // Implemented in the _HorizontalInnerDimension instead.
  @override
  _EnsureVisibleResults _performEnsureVisible(
    RenderObject object, {
    double alignment = 0.0,
    Duration duration = Duration.zero,
    Curve curve = Curves.ease,
    ScrollPositionAlignmentPolicy alignmentPolicy = ScrollPositionAlignmentPolicy.explicit,
    RenderObject? targetRenderObject,
  }) {
    assert(
      false,
      'The _performEnsureVisible method was called for the vertical scrollable '
      'of a TwoDimensionalScrollable. This should not happen as the horizontal '
      'scrollable handles both axes.',
    );
    return (<Future<void>>[], this);
  }

  void _evaluateLockedAxis(Offset offset) {
    assert(lastDragOffset != null);
    final Offset offsetDelta = lastDragOffset! - offset;
    final double axisDifferential = offsetDelta.dx.abs() - offsetDelta.dy.abs();
    if (axisDifferential.abs() >= kTouchSlop) {
      // We have single axis winner.
      lockedAxis = axisDifferential > 0.0 ? Axis.horizontal : Axis.vertical;
    } else {
      lockedAxis = null;
    }
  }

  @override
  void _handleDragDown(DragDownDetails details) {
    switch (diagonalDragBehavior) {
      case DiagonalDragBehavior.none:
        break;
      case DiagonalDragBehavior.weightedEvent:
      case DiagonalDragBehavior.weightedContinuous:
      case DiagonalDragBehavior.free:
        // Initiate hold. If one or the other wins the gesture, cancel the
        // opposite axis.
        horizontalScrollable._handleDragDown(details);
    }
    super._handleDragDown(details);
  }

  @override
  void _handleDragStart(DragStartDetails details) {
    lastDragOffset = details.globalPosition;
    switch (diagonalDragBehavior) {
      case DiagonalDragBehavior.none:
        break;
      case DiagonalDragBehavior.free:
        // Prepare to scroll both.
        // vertical - will call super below after switch.
        horizontalScrollable._handleDragStart(details);
      case DiagonalDragBehavior.weightedEvent:
      case DiagonalDragBehavior.weightedContinuous:
        // See if one axis wins the drag.
        _evaluateLockedAxis(details.globalPosition);
        switch (lockedAxis) {
          case null:
            // Prepare to scroll both, null means no winner yet.
            // vertical - will call super below after switch.
            horizontalScrollable._handleDragStart(details);
          case Axis.horizontal:
            // Prepare to scroll horizontally.
            horizontalScrollable._handleDragStart(details);
            return;
          case Axis.vertical:
          // Prepare to scroll vertically - will call super below after switch.
        }
    }
    super._handleDragStart(details);
  }

  @override
  void _handleDragUpdate(DragUpdateDetails details) {
    final verticalDragDetails = DragUpdateDetails(
      sourceTimeStamp: details.sourceTimeStamp,
      delta: Offset(0.0, details.delta.dy),
      primaryDelta: details.delta.dy,
      globalPosition: details.globalPosition,
      localPosition: details.localPosition,
    );
    final horizontalDragDetails = DragUpdateDetails(
      sourceTimeStamp: details.sourceTimeStamp,
      delta: Offset(details.delta.dx, 0.0),
      primaryDelta: details.delta.dx,
      globalPosition: details.globalPosition,
      localPosition: details.localPosition,
    );

    switch (diagonalDragBehavior) {
      case DiagonalDragBehavior.none:
        // Default gesture handling from super class.
        super._handleDragUpdate(verticalDragDetails);
        return;
      case DiagonalDragBehavior.free:
        // Scroll both axes
        horizontalScrollable._handleDragUpdate(horizontalDragDetails);
        super._handleDragUpdate(verticalDragDetails);
        return;
      case DiagonalDragBehavior.weightedContinuous:
        // Re-evaluate locked axis for every update.
        _evaluateLockedAxis(details.globalPosition);
        lastDragOffset = details.globalPosition;
      case DiagonalDragBehavior.weightedEvent:
        // Lock axis only once per gesture.
        if (lockedAxis == null && lastDragOffset != null) {
          // A winner has not been declared yet.
          // See if one axis has won the drag.
          _evaluateLockedAxis(details.globalPosition);
        }
    }
    switch (lockedAxis) {
      case null:
        // Scroll both - vertical after switch
        horizontalScrollable._handleDragUpdate(horizontalDragDetails);
      case Axis.horizontal:
        // Scroll horizontally
        horizontalScrollable._handleDragUpdate(horizontalDragDetails);
        return;
      case Axis.vertical:
      // Scroll vertically - after switch
    }
    super._handleDragUpdate(verticalDragDetails);
  }

  @override
  void _handleDragEnd(DragEndDetails details) {
    lastDragOffset = null;
    lockedAxis = null;
    final double dx = details.velocity.pixelsPerSecond.dx;
    final double dy = details.velocity.pixelsPerSecond.dy;
    final verticalDragDetails = DragEndDetails(
      velocity: Velocity(pixelsPerSecond: Offset(0.0, dy)),
      primaryVelocity: dy,
    );
    final horizontalDragDetails = DragEndDetails(
      velocity: Velocity(pixelsPerSecond: Offset(dx, 0.0)),
      primaryVelocity: dx,
    );

    switch (diagonalDragBehavior) {
      case DiagonalDragBehavior.none:
        break;
      case DiagonalDragBehavior.weightedEvent:
      case DiagonalDragBehavior.weightedContinuous:
      case DiagonalDragBehavior.free:
        horizontalScrollable._handleDragEnd(horizontalDragDetails);
    }
    super._handleDragEnd(verticalDragDetails);
  }

  @override
  void _handleDragCancel() {
    lastDragOffset = null;
    lockedAxis = null;
    switch (diagonalDragBehavior) {
      case DiagonalDragBehavior.none:
        break;
      case DiagonalDragBehavior.weightedEvent:
      case DiagonalDragBehavior.weightedContinuous:
      case DiagonalDragBehavior.free:
        horizontalScrollable._handleDragCancel();
    }
    super._handleDragCancel();
  }

  @override
  void setCanDrag(bool value) {
    switch (diagonalDragBehavior) {
      case DiagonalDragBehavior.none:
        // If we aren't scrolling diagonally, the default drag gesture recognizer
        // is used.
        super.setCanDrag(value);
        return;
      case DiagonalDragBehavior.weightedEvent:
      case DiagonalDragBehavior.weightedContinuous:
      case DiagonalDragBehavior.free:
        if (value) {
          // Replaces the typical vertical/horizontal drag gesture recognizers
          // with a pan gesture recognizer to allow bidirectional scrolling.
          // Based on the diagonalDragBehavior, valid vertical deltas are
          // applied to this scrollable, while horizontal deltas are routed to
          // the horizontal scrollable.
          _gestureRecognizers = <Type, GestureRecognizerFactory>{
            PanGestureRecognizer: GestureRecognizerFactoryWithHandlers<PanGestureRecognizer>(
              () => PanGestureRecognizer(supportedDevices: _configuration.dragDevices),
              (PanGestureRecognizer instance) {
                instance
                  ..onDown = _handleDragDown
                  ..onStart = _handleDragStart
                  ..onUpdate = _handleDragUpdate
                  ..onEnd = _handleDragEnd
                  ..onCancel = _handleDragCancel
                  ..minFlingDistance = _physics?.minFlingDistance
                  ..minFlingVelocity = _physics?.minFlingVelocity
                  ..maxFlingVelocity = _physics?.maxFlingVelocity
                  ..velocityTrackerBuilder = _configuration.velocityTrackerBuilder(context)
                  ..dragStartBehavior = widget.dragStartBehavior
                  ..gestureSettings = _mediaQueryGestureSettings;
              },
            ),
          };
          // Cancel the active hold/drag (if any) because the gesture recognizers
          // will soon be disposed by our RawGestureDetector, and we won't be
          // receiving pointer up events to cancel the hold/drag.
          _handleDragCancel();
          _lastCanDrag = value;
          _lastAxisDirection = widget.axis;
          if (_gestureDetectorKey.currentState != null) {
            _gestureDetectorKey.currentState!.replaceGestureRecognizers(_gestureRecognizers);
          }
        }
        return;
    }
  }

  @override
  Widget _buildChrome(BuildContext context, Widget child) {
    final details = ScrollableDetails(
      direction: widget.axisDirection,
      controller: _effectiveScrollController,
      clipBehavior: widget.clipBehavior,
    );
    // Skip building a scrollbar here, the dual scrollbar is added in
    // TwoDimensionalScrollableState.
    return _configuration.buildOverscrollIndicator(context, child, details);
  }
}

// Horizontal inner scrollable of 2D scrolling
class _HorizontalInnerDimension extends Scrollable {
  const _HorizontalInnerDimension({
    super.key,
    required this.verticalOuterKey,
    required super.viewportBuilder,
    required super.axisDirection,
    super.controller,
    super.physics,
    super.clipBehavior,
    super.incrementCalculator,
    super.excludeFromSemantics,
    super.dragStartBehavior,
    super.restorationId,
    super.hitTestBehavior,
    this.diagonalDragBehavior = DiagonalDragBehavior.none,
  }) : assert(axisDirection == AxisDirection.left || axisDirection == AxisDirection.right);

  final GlobalKey<ScrollableState> verticalOuterKey;
  final DiagonalDragBehavior diagonalDragBehavior;

  @override
  _HorizontalInnerDimensionState createState() => _HorizontalInnerDimensionState();
}

class _HorizontalInnerDimensionState extends ScrollableState {
  late ScrollableState verticalScrollable;

  GlobalKey<ScrollableState> get verticalOuterKey =>
      (widget as _HorizontalInnerDimension).verticalOuterKey;
  DiagonalDragBehavior get diagonalDragBehavior =>
      (widget as _HorizontalInnerDimension).diagonalDragBehavior;

  @override
  void didChangeDependencies() {
    verticalScrollable = Scrollable.of(context);
    assert(axisDirectionToAxis(verticalScrollable.axisDirection) == Axis.vertical);
    super.didChangeDependencies();
  }

  // Returns the Future from calling ensureVisible for the ScrollPosition, as
  // as well as the vertical ScrollableState instance so its context can be
  // used to check for other ancestor Scrollables in executing ensureVisible.
  @override
  _EnsureVisibleResults _performEnsureVisible(
    RenderObject object, {
    double alignment = 0.0,
    Duration duration = Duration.zero,
    Curve curve = Curves.ease,
    ScrollPositionAlignmentPolicy alignmentPolicy = ScrollPositionAlignmentPolicy.explicit,
    RenderObject? targetRenderObject,
  }) {
    final newFutures = <Future<void>>[
      position.ensureVisible(
        object,
        alignment: alignment,
        duration: duration,
        curve: curve,
        alignmentPolicy: alignmentPolicy,
      ),
      verticalScrollable.position.ensureVisible(
        object,
        alignment: alignment,
        duration: duration,
        curve: curve,
        alignmentPolicy: alignmentPolicy,
      ),
    ];

    return (newFutures, verticalScrollable);
  }

  @override
  void setCanDrag(bool value) {
    switch (diagonalDragBehavior) {
      case DiagonalDragBehavior.none:
        // If we aren't scrolling diagonally, the default drag gesture
        // recognizer is used.
        super.setCanDrag(value);
        return;
      case DiagonalDragBehavior.weightedEvent:
      case DiagonalDragBehavior.weightedContinuous:
      case DiagonalDragBehavior.free:
        if (value) {
          // If a type of diagonal scrolling is enabled, a panning gesture
          // recognizer will be created for the _VerticalOuterDimension. So in
          // this case, the _HorizontalInnerDimension does not require a gesture
          // recognizer, meanwhile we should ensure the outer dimension has
          // updated in case it did not have enough content to enable dragging.
          _gestureRecognizers = const <Type, GestureRecognizerFactory>{};
          verticalOuterKey.currentState!.setCanDrag(value);
          // Cancel the active hold/drag (if any) because the gesture recognizers
          // will soon be disposed by our RawGestureDetector, and we won't be
          // receiving pointer up events to cancel the hold/drag.
          _handleDragCancel();
          _lastCanDrag = value;
          _lastAxisDirection = widget.axis;
          if (_gestureDetectorKey.currentState != null) {
            _gestureDetectorKey.currentState!.replaceGestureRecognizers(_gestureRecognizers);
          }
        }
        return;
    }
  }

  @override
  Widget _buildChrome(BuildContext context, Widget child) {
    final details = ScrollableDetails(
      direction: widget.axisDirection,
      controller: _effectiveScrollController,
      clipBehavior: widget.clipBehavior,
    );
    // Skip building a scrollbar here, the dual scrollbar is added in
    // TwoDimensionalScrollableState.
    return _configuration.buildOverscrollIndicator(context, child, details);
  }
}
