mirror of
https://github.com/flutter/flutter
synced 2024-08-27 20:10:11 +00:00
migrate rendering to nullsafety (#64621)
This commit is contained in:
parent
dcdee4bb0d
commit
8a6a76a334
|
@ -202,6 +202,7 @@ linter:
|
|||
- use_full_hex_values_for_flutter_colors
|
||||
# - use_function_type_syntax_for_parameters # not yet tested
|
||||
# - use_key_in_widget_constructors # not yet tested
|
||||
- use_late_for_private_fields_and_variables
|
||||
- use_rethrow_when_possible
|
||||
# - use_setters_to_change_properties # not yet tested
|
||||
# - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182
|
||||
|
|
|
@ -8,5 +8,6 @@ analyzer:
|
|||
errors:
|
||||
always_require_non_null_named_parameters: false # not needed with nnbd
|
||||
type_init_formals: false # https://github.com/dart-lang/linter/issues/2192
|
||||
unrelated_type_equality_checks: false # https://github.com/dart-lang/linter/issues/2196
|
||||
void_checks: false # https://github.com/dart-lang/linter/issues/2185
|
||||
unnecessary_null_comparison: false # https://github.com/dart-lang/language/issues/1018 , turned off until https://github.com/flutter/flutter/issues/61042
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
/// The Flutter rendering tree.
|
||||
///
|
||||
/// To use, import `package:flutter/rendering.dart`.
|
||||
|
|
|
@ -208,6 +208,20 @@ class _ChainedEvaluation<T> extends Animatable<T> {
|
|||
/// [Tween]s that use dedicated `lerp` methods instead of merely relying on the
|
||||
/// operators (in particular, this allows them to handle null values in a more
|
||||
/// useful manner).
|
||||
///
|
||||
/// ## Nullability
|
||||
///
|
||||
/// The [begin] and [end] fields are nullable; a [Tween] does not have to
|
||||
/// have non-null values specified when it is created.
|
||||
///
|
||||
/// If `T` is nullable, then [lerp] and [transform] may return null.
|
||||
/// This is typically seen in the case where [begin] is null and `t`
|
||||
/// is 0.0, or [end] is null and `t` is 1.0, or both are null (at any
|
||||
/// `t` value).
|
||||
///
|
||||
/// If `T` is not nullable, then [begin] and [end] must both be set to
|
||||
/// non-null values before using [lerp] or [transform], otherwise they
|
||||
/// will throw.
|
||||
class Tween<T extends dynamic> extends Animatable<T> {
|
||||
/// Creates a tween.
|
||||
///
|
||||
|
@ -236,6 +250,9 @@ class Tween<T extends dynamic> extends Animatable<T> {
|
|||
/// The default implementation of this method uses the [+], [-], and [*]
|
||||
/// operators on `T`. The [begin] and [end] properties must therefore be
|
||||
/// non-null by the time this method is called.
|
||||
///
|
||||
/// In general, however, it is possible for this to return null, especially
|
||||
/// when `t`=0.0 and [begin] is null, or `t`=1.0 and [end] is null.
|
||||
@protected
|
||||
T lerp(double t) {
|
||||
assert(begin != null);
|
||||
|
@ -291,6 +308,9 @@ class ReverseTween<T> extends Tween<T> {
|
|||
/// This class specializes the interpolation of [Tween<Color>] to use
|
||||
/// [Color.lerp].
|
||||
///
|
||||
/// The values can be null, representing no color (which is distinct to
|
||||
/// transparent black, as represented by [Colors.transparent]).
|
||||
///
|
||||
/// See [Tween] for a discussion on how to use interpolation objects.
|
||||
class ColorTween extends Tween<Color?> {
|
||||
/// Creates a [Color] tween.
|
||||
|
@ -314,6 +334,8 @@ class ColorTween extends Tween<Color?> {
|
|||
/// This class specializes the interpolation of [Tween<Size>] to use
|
||||
/// [Size.lerp].
|
||||
///
|
||||
/// The values can be null, representing [Size.zero].
|
||||
///
|
||||
/// See [Tween] for a discussion on how to use interpolation objects.
|
||||
class SizeTween extends Tween<Size?> {
|
||||
/// Creates a [Size] tween.
|
||||
|
@ -332,6 +354,9 @@ class SizeTween extends Tween<Size?> {
|
|||
/// This class specializes the interpolation of [Tween<Rect>] to use
|
||||
/// [Rect.lerp].
|
||||
///
|
||||
/// The values can be null, representing a zero-sized rectangle at the
|
||||
/// origin ([Rect.zero]).
|
||||
///
|
||||
/// See [Tween] for a discussion on how to use interpolation objects.
|
||||
class RectTween extends Tween<Rect?> {
|
||||
/// Creates a [Rect] tween.
|
||||
|
@ -355,6 +380,9 @@ class RectTween extends Tween<Rect?> {
|
|||
/// This is the closest approximation to a linear tween that is possible with an
|
||||
/// integer. Compare to [StepTween] and [Tween<double>].
|
||||
///
|
||||
/// The [begin] and [end] values must be set to non-null values before
|
||||
/// calling [lerp] or [transform].
|
||||
///
|
||||
/// See [Tween] for a discussion on how to use interpolation objects.
|
||||
class IntTween extends Tween<int> {
|
||||
/// Creates an int tween.
|
||||
|
@ -380,6 +408,9 @@ class IntTween extends Tween<int> {
|
|||
/// This results in a value that is never greater than the equivalent
|
||||
/// value from a linear double interpolation. Compare to [IntTween].
|
||||
///
|
||||
/// The [begin] and [end] values must be set to non-null values before
|
||||
/// calling [lerp] or [transform].
|
||||
///
|
||||
/// See [Tween] for a discussion on how to use interpolation objects.
|
||||
class StepTween extends Tween<int> {
|
||||
/// Creates an [int] tween that floors.
|
||||
|
|
|
@ -3377,13 +3377,10 @@ abstract class DiagnosticableTree with Diagnosticable {
|
|||
///
|
||||
/// * [toString], for a brief description of the object.
|
||||
/// * [toStringDeep], for a description of the subtree rooted at this object.
|
||||
String? toStringShallow({
|
||||
String toStringShallow({
|
||||
String joiner = ', ',
|
||||
DiagnosticLevel minLevel = DiagnosticLevel.debug,
|
||||
}) {
|
||||
if (kReleaseMode) {
|
||||
return toString();
|
||||
}
|
||||
String? shallowString;
|
||||
assert(() {
|
||||
final StringBuffer result = StringBuffer();
|
||||
|
@ -3398,7 +3395,7 @@ abstract class DiagnosticableTree with Diagnosticable {
|
|||
shallowString = result.toString();
|
||||
return true;
|
||||
}());
|
||||
return shallowString;
|
||||
return shallowString ?? toString();
|
||||
}
|
||||
|
||||
/// Returns a string representation of this node and its descendants.
|
||||
|
@ -3470,13 +3467,10 @@ mixin DiagnosticableTreeMixin implements DiagnosticableTree {
|
|||
}
|
||||
|
||||
@override
|
||||
String? toStringShallow({
|
||||
String toStringShallow({
|
||||
String joiner = ', ',
|
||||
DiagnosticLevel minLevel = DiagnosticLevel.debug,
|
||||
}) {
|
||||
if (kReleaseMode) {
|
||||
return toString();
|
||||
}
|
||||
String? shallowString;
|
||||
assert(() {
|
||||
final StringBuffer result = StringBuffer();
|
||||
|
@ -3491,7 +3485,7 @@ mixin DiagnosticableTreeMixin implements DiagnosticableTree {
|
|||
shallowString = result.toString();
|
||||
return true;
|
||||
}());
|
||||
return shallowString;
|
||||
return shallowString ?? toString();
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -291,6 +291,7 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
|
|||
event is PointerHoverEvent ||
|
||||
event is PointerAddedEvent ||
|
||||
event is PointerRemovedEvent) {
|
||||
assert(event.position != null);
|
||||
dispatchEvent(event, hitTestResult);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ class PointerEventConverter {
|
|||
static Iterable<PointerEvent> expand(Iterable<ui.PointerData> data, double devicePixelRatio) sync* {
|
||||
for (final ui.PointerData datum in data) {
|
||||
final Offset position = Offset(datum.physicalX, datum.physicalY) / devicePixelRatio;
|
||||
assert(position != null);
|
||||
final Offset delta = Offset(datum.physicalDeltaX, datum.physicalDeltaY) / devicePixelRatio;
|
||||
final double radiusMinor = _toLogicalPixels(datum.radiusMinor, devicePixelRatio);
|
||||
final double radiusMajor = _toLogicalPixels(datum.radiusMajor, devicePixelRatio);
|
||||
|
|
|
@ -44,6 +44,9 @@ class PlaceholderDimensions {
|
|||
}) : assert(size != null),
|
||||
assert(alignment != null);
|
||||
|
||||
/// A constant representing an empty placeholder.
|
||||
static const PlaceholderDimensions empty = PlaceholderDimensions(size: Size.zero, alignment: ui.PlaceholderAlignment.bottom);
|
||||
|
||||
/// Width and height dimensions of the placeholder.
|
||||
final Size size;
|
||||
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/animation.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
|
@ -76,13 +74,13 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
|
|||
/// The arguments [duration], [curve], [alignment], and [vsync] must
|
||||
/// not be null.
|
||||
RenderAnimatedSize({
|
||||
@required TickerProvider vsync,
|
||||
@required Duration duration,
|
||||
Duration reverseDuration,
|
||||
required TickerProvider vsync,
|
||||
required Duration duration,
|
||||
Duration? reverseDuration,
|
||||
Curve curve = Curves.linear,
|
||||
AlignmentGeometry alignment = Alignment.center,
|
||||
TextDirection textDirection,
|
||||
RenderBox child,
|
||||
TextDirection? textDirection,
|
||||
RenderBox? child,
|
||||
}) : assert(vsync != null),
|
||||
assert(duration != null),
|
||||
assert(curve != null),
|
||||
|
@ -102,11 +100,11 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
|
|||
);
|
||||
}
|
||||
|
||||
AnimationController _controller;
|
||||
CurvedAnimation _animation;
|
||||
late final AnimationController _controller;
|
||||
late final CurvedAnimation _animation;
|
||||
final SizeTween _sizeTween = SizeTween();
|
||||
bool _hasVisualOverflow;
|
||||
double _lastValue;
|
||||
late bool _hasVisualOverflow;
|
||||
double? _lastValue;
|
||||
|
||||
/// The state this size animation is in.
|
||||
///
|
||||
|
@ -116,7 +114,7 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
|
|||
RenderAnimatedSizeState _state = RenderAnimatedSizeState.start;
|
||||
|
||||
/// The duration of the animation.
|
||||
Duration get duration => _controller.duration;
|
||||
Duration get duration => _controller.duration!;
|
||||
set duration(Duration value) {
|
||||
assert(value != null);
|
||||
if (value == _controller.duration)
|
||||
|
@ -125,8 +123,8 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
|
|||
}
|
||||
|
||||
/// The duration of the animation when running in reverse.
|
||||
Duration get reverseDuration => _controller.reverseDuration;
|
||||
set reverseDuration(Duration value) {
|
||||
Duration? get reverseDuration => _controller.reverseDuration;
|
||||
set reverseDuration(Duration? value) {
|
||||
if (value == _controller.reverseDuration)
|
||||
return;
|
||||
_controller.reverseDuration = value;
|
||||
|
@ -164,7 +162,7 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
|
|||
super.detach();
|
||||
}
|
||||
|
||||
Size get _animatedSize {
|
||||
Size? get _animatedSize {
|
||||
return _sizeTween.evaluate(_animation);
|
||||
}
|
||||
|
||||
|
@ -181,7 +179,7 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
|
|||
return;
|
||||
}
|
||||
|
||||
child.layout(constraints, parentUsesSize: true);
|
||||
child!.layout(constraints, parentUsesSize: true);
|
||||
|
||||
assert(_state != null);
|
||||
switch (_state) {
|
||||
|
@ -199,11 +197,11 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
|
|||
break;
|
||||
}
|
||||
|
||||
size = constraints.constrain(_animatedSize);
|
||||
size = constraints.constrain(_animatedSize!);
|
||||
alignChild();
|
||||
|
||||
if (size.width < _sizeTween.end.width ||
|
||||
size.height < _sizeTween.end.height)
|
||||
if (size.width < _sizeTween.end!.width ||
|
||||
size.height < _sizeTween.end!.height)
|
||||
_hasVisualOverflow = true;
|
||||
}
|
||||
|
||||
|
@ -217,7 +215,7 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
|
|||
/// We have the initial size to animate from, but we do not have the target
|
||||
/// size to animate to, so we set both ends to child's size.
|
||||
void _layoutStart() {
|
||||
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child.size);
|
||||
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child!.size);
|
||||
_state = RenderAnimatedSizeState.stable;
|
||||
}
|
||||
|
||||
|
@ -227,14 +225,14 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
|
|||
/// If during animation the size of the child changes we restart the
|
||||
/// animation.
|
||||
void _layoutStable() {
|
||||
if (_sizeTween.end != child.size) {
|
||||
if (_sizeTween.end != child!.size) {
|
||||
_sizeTween.begin = size;
|
||||
_sizeTween.end = debugAdoptSize(child.size);
|
||||
_sizeTween.end = debugAdoptSize(child!.size);
|
||||
_restartAnimation();
|
||||
_state = RenderAnimatedSizeState.changed;
|
||||
} else if (_controller.value == _controller.upperBound) {
|
||||
// Animation finished. Reset target sizes.
|
||||
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child.size);
|
||||
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child!.size);
|
||||
} else if (!_controller.isAnimating) {
|
||||
_controller.forward(); // resume the animation after being detached
|
||||
}
|
||||
|
@ -247,9 +245,9 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
|
|||
/// changes again, we match the child's size, restart animation and go to
|
||||
/// unstable state.
|
||||
void _layoutChanged() {
|
||||
if (_sizeTween.end != child.size) {
|
||||
if (_sizeTween.end != child!.size) {
|
||||
// Child size changed again. Match the child's size and restart animation.
|
||||
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child.size);
|
||||
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child!.size);
|
||||
_restartAnimation();
|
||||
_state = RenderAnimatedSizeState.unstable;
|
||||
} else {
|
||||
|
@ -264,9 +262,9 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
|
|||
///
|
||||
/// Continue tracking the child's size until is stabilizes.
|
||||
void _layoutUnstable() {
|
||||
if (_sizeTween.end != child.size) {
|
||||
if (_sizeTween.end != child!.size) {
|
||||
// Still unstable. Continue tracking the child.
|
||||
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child.size);
|
||||
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child!.size);
|
||||
_restartAnimation();
|
||||
} else {
|
||||
// Child size stabilized.
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'dart:typed_data';
|
||||
|
@ -50,8 +48,8 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
|||
}
|
||||
|
||||
/// The current [RendererBinding], if one has been created.
|
||||
static RendererBinding get instance => _instance;
|
||||
static RendererBinding _instance;
|
||||
static RendererBinding? get instance => _instance;
|
||||
static RendererBinding? _instance;
|
||||
|
||||
@override
|
||||
void initServiceExtensions() {
|
||||
|
@ -145,20 +143,25 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
|||
///
|
||||
/// Called automatically when the binding is created.
|
||||
void initRenderView() {
|
||||
assert(renderView == null);
|
||||
assert(!_debugIsRenderViewInitialized);
|
||||
assert(() {
|
||||
_debugIsRenderViewInitialized = true;
|
||||
return true;
|
||||
}());
|
||||
renderView = RenderView(configuration: createViewConfiguration(), window: window);
|
||||
renderView.prepareInitialFrame();
|
||||
}
|
||||
bool _debugIsRenderViewInitialized = false;
|
||||
|
||||
/// The object that manages state about currently connected mice, for hover
|
||||
/// notification.
|
||||
MouseTracker get mouseTracker => _mouseTracker;
|
||||
MouseTracker _mouseTracker;
|
||||
MouseTracker get mouseTracker => _mouseTracker!;
|
||||
MouseTracker? _mouseTracker;
|
||||
|
||||
/// The render tree's owner, which maintains dirty state for layout,
|
||||
/// composite, paint, and accessibility semantics.
|
||||
PipelineOwner get pipelineOwner => _pipelineOwner;
|
||||
PipelineOwner _pipelineOwner;
|
||||
late PipelineOwner _pipelineOwner;
|
||||
|
||||
/// The render tree that's attached to the output surface.
|
||||
RenderView get renderView => _pipelineOwner.rootNode as RenderView;
|
||||
|
@ -239,25 +242,26 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
|||
);
|
||||
}
|
||||
|
||||
SemanticsHandle _semanticsHandle;
|
||||
SemanticsHandle? _semanticsHandle;
|
||||
|
||||
/// Creates a [MouseTracker] which manages state about currently connected
|
||||
/// mice, for hover notification.
|
||||
///
|
||||
/// Used by testing framework to reinitialize the mouse tracker between tests.
|
||||
@visibleForTesting
|
||||
void initMouseTracker([MouseTracker tracker]) {
|
||||
void initMouseTracker([MouseTracker? tracker]) {
|
||||
_mouseTracker?.dispose();
|
||||
_mouseTracker = tracker ?? MouseTracker();
|
||||
}
|
||||
|
||||
@override // from GestureBinding
|
||||
void dispatchEvent(PointerEvent event, HitTestResult hitTestResult) {
|
||||
void dispatchEvent(PointerEvent event, HitTestResult? hitTestResult) {
|
||||
if (hitTestResult != null ||
|
||||
event is PointerHoverEvent ||
|
||||
event is PointerAddedEvent ||
|
||||
event is PointerRemovedEvent) {
|
||||
_mouseTracker.updateWithEvent(event,
|
||||
assert(event.position != null);
|
||||
_mouseTracker!.updateWithEvent(event,
|
||||
() => hitTestResult ?? renderView.hitTestMouseTrackers(event.position));
|
||||
}
|
||||
super.dispatchEvent(event, hitTestResult);
|
||||
|
@ -278,7 +282,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
|||
}
|
||||
}
|
||||
|
||||
void _handleSemanticsAction(int id, SemanticsAction action, ByteData args) {
|
||||
void _handleSemanticsAction(int id, SemanticsAction action, ByteData? args) {
|
||||
_pipelineOwner.semanticsOwner?.performAction(
|
||||
id,
|
||||
action,
|
||||
|
@ -306,13 +310,13 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
|||
_debugMouseTrackerUpdateScheduled = true;
|
||||
return true;
|
||||
}());
|
||||
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
|
||||
SchedulerBinding.instance!.addPostFrameCallback((Duration duration) {
|
||||
assert(_debugMouseTrackerUpdateScheduled);
|
||||
assert(() {
|
||||
_debugMouseTrackerUpdateScheduled = false;
|
||||
return true;
|
||||
}());
|
||||
_mouseTracker.updateAllDevices(renderView.hitTestMouseTrackers);
|
||||
_mouseTracker!.updateAllDevices(renderView.hitTestMouseTrackers);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -455,29 +459,31 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
|
|||
@override
|
||||
void hitTest(HitTestResult result, Offset position) {
|
||||
assert(renderView != null);
|
||||
assert(result != null);
|
||||
assert(position != null);
|
||||
renderView.hitTest(result, position: position);
|
||||
super.hitTest(result, position);
|
||||
}
|
||||
|
||||
Future<void> _forceRepaint() {
|
||||
RenderObjectVisitor visitor;
|
||||
late RenderObjectVisitor visitor;
|
||||
visitor = (RenderObject child) {
|
||||
child.markNeedsPaint();
|
||||
child.visitChildren(visitor);
|
||||
};
|
||||
instance?.renderView?.visitChildren(visitor);
|
||||
instance?.renderView.visitChildren(visitor);
|
||||
return endOfFrame;
|
||||
}
|
||||
}
|
||||
|
||||
/// Prints a textual representation of the entire render tree.
|
||||
void debugDumpRenderTree() {
|
||||
debugPrint(RendererBinding.instance?.renderView?.toStringDeep() ?? 'Render tree unavailable.');
|
||||
debugPrint(RendererBinding.instance?.renderView.toStringDeep() ?? 'Render tree unavailable.');
|
||||
}
|
||||
|
||||
/// Prints a textual representation of the entire layer tree.
|
||||
void debugDumpLayerTree() {
|
||||
debugPrint(RendererBinding.instance?.renderView?.debugLayer?.toStringDeep() ?? 'Layer tree unavailable.');
|
||||
debugPrint(RendererBinding.instance?.renderView.debugLayer?.toStringDeep() ?? 'Layer tree unavailable.');
|
||||
}
|
||||
|
||||
/// Prints a textual representation of the entire semantics tree.
|
||||
|
@ -487,7 +493,7 @@ void debugDumpLayerTree() {
|
|||
/// The order in which the children of a [SemanticsNode] will be printed is
|
||||
/// controlled by the [childOrder] parameter.
|
||||
void debugDumpSemanticsTree(DebugSemanticsDumpOrder childOrder) {
|
||||
debugPrint(RendererBinding.instance?.renderView?.debugSemantics?.toStringDeep(childOrder: childOrder) ?? 'Semantics not collected.');
|
||||
debugPrint(RendererBinding.instance?.renderView.debugSemantics?.toStringDeep(childOrder: childOrder) ?? 'Semantics not collected.');
|
||||
}
|
||||
|
||||
/// A concrete binding for applications that use the Rendering framework
|
||||
|
@ -502,7 +508,7 @@ class RenderingFlutterBinding extends BindingBase with GestureBinding, Scheduler
|
|||
///
|
||||
/// The `root` render box is attached directly to the [renderView] and is
|
||||
/// given constraints that require it to fill the window.
|
||||
RenderingFlutterBinding({ RenderBox root }) {
|
||||
RenderingFlutterBinding({ RenderBox? root }) {
|
||||
assert(renderView != null);
|
||||
renderView.child = root;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui' as ui show lerpDouble;
|
||||
|
||||
|
@ -19,7 +17,7 @@ import 'object.dart';
|
|||
class _DebugSize extends Size {
|
||||
_DebugSize(Size source, this._owner, this._canBeUsedByParent) : super.copy(source);
|
||||
final RenderBox _owner;
|
||||
final bool/*!*/ _canBeUsedByParent;
|
||||
final bool _canBeUsedByParent;
|
||||
}
|
||||
|
||||
/// Immutable layout constraints for [RenderBox] layout.
|
||||
|
@ -112,8 +110,8 @@ class BoxConstraints extends Constraints {
|
|||
/// being tight if the value is non-null, is tight if the value is not
|
||||
/// infinite.
|
||||
const BoxConstraints.tightFor({
|
||||
double width,
|
||||
double height,
|
||||
double? width,
|
||||
double? height,
|
||||
}) : minWidth = width ?? 0.0,
|
||||
maxWidth = width ?? double.infinity,
|
||||
minHeight = height ?? 0.0,
|
||||
|
@ -146,8 +144,8 @@ class BoxConstraints extends Constraints {
|
|||
/// If width or height is given, the constraints will require exactly the
|
||||
/// given value in the given dimension.
|
||||
const BoxConstraints.expand({
|
||||
double width,
|
||||
double height,
|
||||
double? width,
|
||||
double? height,
|
||||
}) : minWidth = width ?? double.infinity,
|
||||
maxWidth = width ?? double.infinity,
|
||||
minHeight = height ?? double.infinity,
|
||||
|
@ -171,10 +169,10 @@ class BoxConstraints extends Constraints {
|
|||
|
||||
/// Creates a copy of this box constraints but with the given fields replaced with the new values.
|
||||
BoxConstraints copyWith({
|
||||
double minWidth,
|
||||
double maxWidth,
|
||||
double minHeight,
|
||||
double maxHeight,
|
||||
double? minWidth,
|
||||
double? maxWidth,
|
||||
double? minHeight,
|
||||
double? maxHeight,
|
||||
}) {
|
||||
return BoxConstraints(
|
||||
minWidth: minWidth ?? this.minWidth,
|
||||
|
@ -215,22 +213,22 @@ class BoxConstraints extends Constraints {
|
|||
/// as close as possible to the original constraints.
|
||||
BoxConstraints enforce(BoxConstraints constraints) {
|
||||
return BoxConstraints(
|
||||
minWidth: minWidth.clamp(constraints.minWidth, constraints.maxWidth) as double,
|
||||
maxWidth: maxWidth.clamp(constraints.minWidth, constraints.maxWidth) as double,
|
||||
minHeight: minHeight.clamp(constraints.minHeight, constraints.maxHeight) as double,
|
||||
maxHeight: maxHeight.clamp(constraints.minHeight, constraints.maxHeight) as double,
|
||||
minWidth: minWidth.clamp(constraints.minWidth, constraints.maxWidth),
|
||||
maxWidth: maxWidth.clamp(constraints.minWidth, constraints.maxWidth),
|
||||
minHeight: minHeight.clamp(constraints.minHeight, constraints.maxHeight),
|
||||
maxHeight: maxHeight.clamp(constraints.minHeight, constraints.maxHeight),
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns new box constraints with a tight width and/or height as close to
|
||||
/// the given width and height as possible while still respecting the original
|
||||
/// box constraints.
|
||||
BoxConstraints tighten({ double width, double height }) {
|
||||
BoxConstraints tighten({ double? width, double? height }) {
|
||||
return BoxConstraints(
|
||||
minWidth: width == null ? minWidth : width.clamp(minWidth, maxWidth) as double,
|
||||
maxWidth: width == null ? maxWidth : width.clamp(minWidth, maxWidth) as double,
|
||||
minHeight: height == null ? minHeight : height.clamp(minHeight, maxHeight) as double,
|
||||
maxHeight: height == null ? maxHeight : height.clamp(minHeight, maxHeight) as double,
|
||||
minWidth: width == null ? minWidth : width.clamp(minWidth, maxWidth),
|
||||
maxWidth: width == null ? maxWidth : width.clamp(minWidth, maxWidth),
|
||||
minHeight: height == null ? minHeight : height.clamp(minHeight, maxHeight),
|
||||
maxHeight: height == null ? maxHeight : height.clamp(minHeight, maxHeight),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -256,14 +254,14 @@ class BoxConstraints extends Constraints {
|
|||
/// possible to the given width.
|
||||
double constrainWidth([ double width = double.infinity ]) {
|
||||
assert(debugAssertIsValid());
|
||||
return width.clamp(minWidth, maxWidth) as double;
|
||||
return width.clamp(minWidth, maxWidth);
|
||||
}
|
||||
|
||||
/// Returns the height that both satisfies the constraints and is as close as
|
||||
/// possible to the given height.
|
||||
double constrainHeight([ double height = double.infinity ]) {
|
||||
assert(debugAssertIsValid());
|
||||
return height.clamp(minHeight, maxHeight) as double;
|
||||
return height.clamp(minHeight, maxHeight);
|
||||
}
|
||||
|
||||
Size _debugPropagateDebugSize(Size size, Size result) {
|
||||
|
@ -468,12 +466,12 @@ class BoxConstraints extends Constraints {
|
|||
/// object whose fields are all set to 0.0.
|
||||
///
|
||||
/// {@macro dart.ui.shadow.lerp}
|
||||
static BoxConstraints lerp(BoxConstraints/*?*/ a, BoxConstraints/*?*/ b, double t) {
|
||||
static BoxConstraints? lerp(BoxConstraints? a, BoxConstraints? b, double t) {
|
||||
assert(t != null);
|
||||
if (a == null && b == null)
|
||||
return null;
|
||||
if (a == null)
|
||||
return b * t;
|
||||
return b! * t;
|
||||
if (b == null)
|
||||
return a * (1.0 - t);
|
||||
assert(a.debugAssertIsValid());
|
||||
|
@ -483,10 +481,10 @@ class BoxConstraints extends Constraints {
|
|||
assert((a.minHeight.isFinite && b.minHeight.isFinite) || (a.minHeight == double.infinity && b.minHeight == double.infinity), 'Cannot interpolate between finite constraints and unbounded constraints.');
|
||||
assert((a.maxHeight.isFinite && b.maxHeight.isFinite) || (a.maxHeight == double.infinity && b.maxHeight == double.infinity), 'Cannot interpolate between finite constraints and unbounded constraints.');
|
||||
return BoxConstraints(
|
||||
minWidth: a.minWidth.isFinite ? ui.lerpDouble(a.minWidth, b.minWidth, t) : double.infinity,
|
||||
maxWidth: a.maxWidth.isFinite ? ui.lerpDouble(a.maxWidth, b.maxWidth, t) : double.infinity,
|
||||
minHeight: a.minHeight.isFinite ? ui.lerpDouble(a.minHeight, b.minHeight, t) : double.infinity,
|
||||
maxHeight: a.maxHeight.isFinite ? ui.lerpDouble(a.maxHeight, b.maxHeight, t) : double.infinity,
|
||||
minWidth: a.minWidth.isFinite ? ui.lerpDouble(a.minWidth, b.minWidth, t)! : double.infinity,
|
||||
maxWidth: a.maxWidth.isFinite ? ui.lerpDouble(a.maxWidth, b.maxWidth, t)! : double.infinity,
|
||||
minHeight: a.minHeight.isFinite ? ui.lerpDouble(a.minHeight, b.minHeight, t)! : double.infinity,
|
||||
maxHeight: a.maxHeight.isFinite ? ui.lerpDouble(a.maxHeight, b.maxHeight, t)! : double.infinity,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -512,7 +510,7 @@ class BoxConstraints extends Constraints {
|
|||
@override
|
||||
bool debugAssertIsValid({
|
||||
bool isAppliedConstraint = false,
|
||||
InformationCollector informationCollector,
|
||||
InformationCollector? informationCollector,
|
||||
}) {
|
||||
assert(() {
|
||||
void throwError(DiagnosticsNode message) {
|
||||
|
@ -636,6 +634,18 @@ class BoxConstraints extends Constraints {
|
|||
/// [RenderBox]es.
|
||||
typedef BoxHitTest = bool Function(BoxHitTestResult result, Offset position);
|
||||
|
||||
/// Method signature for hit testing a [RenderBox] with a manually
|
||||
/// managed position (one that is passed out-of-band).
|
||||
///
|
||||
/// Used by [RenderSliverSingleBoxAdapter.hitTestBoxChild] to hit test
|
||||
/// [RenderBox] children of a [RenderSliver].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [RenderBox.hitTest], which documents more details around hit testing
|
||||
/// [RenderBox]es.
|
||||
typedef BoxHitTestWithOutOfBandPosition = bool Function(BoxHitTestResult result);
|
||||
|
||||
/// The result of performing a hit test on [RenderBox]es.
|
||||
///
|
||||
/// An instance of this class is provided to [RenderBox.hitTest] to record the
|
||||
|
@ -725,10 +735,11 @@ class BoxHitTestResult extends HitTestResult {
|
|||
/// * [addWithRawTransform], which takes a transform matrix that is directly
|
||||
/// used to transform the position without any pre-processing.
|
||||
bool addWithPaintTransform({
|
||||
@required Matrix4 transform,
|
||||
@required Offset position,
|
||||
@required BoxHitTest hitTest,
|
||||
required Matrix4? transform,
|
||||
required Offset position,
|
||||
required BoxHitTest hitTest,
|
||||
}) {
|
||||
assert(position != null);
|
||||
assert(hitTest != null);
|
||||
if (transform != null) {
|
||||
transform = Matrix4.tryInvert(PointerEvent.removePerspectiveTransform(transform));
|
||||
|
@ -763,14 +774,13 @@ class BoxHitTestResult extends HitTestResult {
|
|||
/// * [addWithPaintTransform], which takes a generic paint transform matrix and
|
||||
/// documents the intended usage of this API in more detail.
|
||||
bool addWithPaintOffset({
|
||||
@required Offset offset,
|
||||
@required Offset position,
|
||||
@required BoxHitTest hitTest,
|
||||
required Offset? offset,
|
||||
required Offset position,
|
||||
required BoxHitTest hitTest,
|
||||
}) {
|
||||
assert(position != null);
|
||||
assert(hitTest != null);
|
||||
final Offset transformedPosition = position == null || offset == null
|
||||
? position
|
||||
: position - offset;
|
||||
final Offset transformedPosition = offset == null ? position : position - offset;
|
||||
if (offset != null) {
|
||||
pushOffset(-offset);
|
||||
}
|
||||
|
@ -796,24 +806,20 @@ class BoxHitTestResult extends HitTestResult {
|
|||
///
|
||||
/// The function returns the return value of the `hitTest` callback.
|
||||
///
|
||||
/// The `position` argument may be null, which will be forwarded to the
|
||||
/// `hitTest` callback as-is. Using null as the position can be useful if
|
||||
/// the child speaks a different hit test protocol then the parent and the
|
||||
/// position is not required to do the actual hit testing in that protocol.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [addWithPaintTransform], which accomplishes the same thing, but takes a
|
||||
/// _paint_ transform matrix.
|
||||
bool addWithRawTransform({
|
||||
@required Matrix4 transform,
|
||||
@required Offset position,
|
||||
@required BoxHitTest hitTest,
|
||||
required Matrix4? transform,
|
||||
required Offset position,
|
||||
required BoxHitTest hitTest,
|
||||
}) {
|
||||
assert(position != null);
|
||||
assert(hitTest != null);
|
||||
final Offset transformedPosition = position == null || transform == null
|
||||
? position
|
||||
: MatrixUtils.transformPoint(transform, position);
|
||||
assert(position != null);
|
||||
final Offset transformedPosition = transform == null ?
|
||||
position : MatrixUtils.transformPoint(transform, position);
|
||||
if (transform != null) {
|
||||
pushTransform(transform);
|
||||
}
|
||||
|
@ -823,6 +829,60 @@ class BoxHitTestResult extends HitTestResult {
|
|||
}
|
||||
return isHit;
|
||||
}
|
||||
|
||||
/// Pass-through method for adding a hit test while manually managing
|
||||
/// the position transformation logic.
|
||||
///
|
||||
/// The actual hit testing of the child needs to be implemented in the
|
||||
/// provided `hitTest` callback. The position needs to be handled by
|
||||
/// the caller.
|
||||
///
|
||||
/// The function returns the return value of the `hitTest` callback.
|
||||
///
|
||||
/// A `paintOffset`, `paintTransform`, or `rawTransform` should be
|
||||
/// passed to the method to update the hit test stack.
|
||||
///
|
||||
/// * `paintOffset` has the semantics of the `offset` passed to
|
||||
/// [addWithPaintOffset].
|
||||
///
|
||||
/// * `paintTransform` has the semantics of the `transform` passed to
|
||||
/// [addWithPaintTransform], except that it must be invertible; it
|
||||
/// is the responsibility of the caller to ensure this.
|
||||
///
|
||||
/// * `rawTransform` has the semantics of the `transform` passed to
|
||||
/// [addWithRawTransform].
|
||||
///
|
||||
/// Exactly one of these must be non-null.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [addWithPaintTransform], which takes a generic paint transform matrix and
|
||||
/// documents the intended usage of this API in more detail.
|
||||
bool addWithOutOfBandPosition({
|
||||
Offset? paintOffset,
|
||||
Matrix4? paintTransform,
|
||||
Matrix4? rawTransform,
|
||||
required BoxHitTestWithOutOfBandPosition hitTest,
|
||||
}) {
|
||||
assert(hitTest != null);
|
||||
assert((paintOffset == null && paintTransform == null && rawTransform != null) ||
|
||||
(paintOffset == null && paintTransform != null && rawTransform == null) ||
|
||||
(paintOffset != null && paintTransform == null && rawTransform == null),
|
||||
'Exactly one transform or offset argument must be provided.');
|
||||
if (paintOffset != null) {
|
||||
pushOffset(-paintOffset);
|
||||
} else if (rawTransform != null) {
|
||||
pushTransform(rawTransform);
|
||||
} else {
|
||||
assert(paintTransform != null);
|
||||
paintTransform = Matrix4.tryInvert(PointerEvent.removePerspectiveTransform(paintTransform!));
|
||||
assert(paintTransform != null, 'paintTransform must be invertible.');
|
||||
pushTransform(paintTransform!);
|
||||
}
|
||||
final bool isHit = hitTest(this);
|
||||
popTransform();
|
||||
return isHit;
|
||||
}
|
||||
}
|
||||
|
||||
/// A hit test entry used by [RenderBox].
|
||||
|
@ -1294,9 +1354,9 @@ abstract class RenderBox extends RenderObject {
|
|||
child.parentData = BoxParentData();
|
||||
}
|
||||
|
||||
Map<_IntrinsicDimensionsCacheEntry, double/*!*/> _cachedIntrinsicDimensions;
|
||||
Map<_IntrinsicDimensionsCacheEntry, double>? _cachedIntrinsicDimensions;
|
||||
|
||||
double/*!*/ _computeIntrinsicDimension(_IntrinsicDimension dimension, double argument, double/*!*/ computer(double argument)) {
|
||||
double _computeIntrinsicDimension(_IntrinsicDimension dimension, double argument, double computer(double argument)) {
|
||||
assert(RenderObject.debugCheckingIntrinsics || !debugDoingThisResize); // performResize should not depend on anything except the incoming constraints
|
||||
bool shouldCache = true;
|
||||
assert(() {
|
||||
|
@ -1308,7 +1368,7 @@ abstract class RenderBox extends RenderObject {
|
|||
}());
|
||||
if (shouldCache) {
|
||||
_cachedIntrinsicDimensions ??= <_IntrinsicDimensionsCacheEntry, double>{};
|
||||
return _cachedIntrinsicDimensions.putIfAbsent(
|
||||
return _cachedIntrinsicDimensions!.putIfAbsent(
|
||||
_IntrinsicDimensionsCacheEntry(dimension, argument),
|
||||
() => computer(argument),
|
||||
);
|
||||
|
@ -1332,9 +1392,12 @@ abstract class RenderBox extends RenderObject {
|
|||
///
|
||||
/// Do not override this method. Instead, implement [computeMinIntrinsicWidth].
|
||||
@mustCallSuper
|
||||
double getMinIntrinsicWidth(double/*!*/ height) {
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
assert(() {
|
||||
if (height == null) {
|
||||
// `height` has a non-nullable return type, but might be null when
|
||||
// running with weak checking, so we need to null check it anyway (and
|
||||
// ignore the warning that the null-handling logic is dead code).
|
||||
if (height == null) { // ignore: dead_code
|
||||
throw FlutterError.fromParts(<DiagnosticsNode>[
|
||||
ErrorSummary('The height argument to getMinIntrinsicWidth was null.'),
|
||||
ErrorDescription('The argument to getMinIntrinsicWidth must not be negative or null.'),
|
||||
|
@ -1455,7 +1518,7 @@ abstract class RenderBox extends RenderObject {
|
|||
/// * [computeMaxIntrinsicWidth], which computes the smallest width beyond
|
||||
/// which increasing the width never decreases the preferred height.
|
||||
@protected
|
||||
double/*!*/ computeMinIntrinsicWidth(double/*!*/ height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
@ -1477,9 +1540,12 @@ abstract class RenderBox extends RenderObject {
|
|||
/// Do not override this method. Instead, implement
|
||||
/// [computeMaxIntrinsicWidth].
|
||||
@mustCallSuper
|
||||
double getMaxIntrinsicWidth(double/*!*/ height) {
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
assert(() {
|
||||
if (height == null) {
|
||||
// `height` has a non-nullable return type, but might be null when
|
||||
// running with weak checking, so we need to null check it anyway (and
|
||||
// ignore the warning that the null-handling logic is dead code).
|
||||
if (height == null) { // ignore: dead_code
|
||||
throw FlutterError.fromParts(<DiagnosticsNode>[
|
||||
ErrorSummary('The height argument to getMaxIntrinsicWidth was null.'),
|
||||
ErrorDescription('The argument to getMaxIntrinsicWidth must not be negative or null.'),
|
||||
|
@ -1535,7 +1601,7 @@ abstract class RenderBox extends RenderObject {
|
|||
///
|
||||
/// * [computeMinIntrinsicWidth], which has usage examples.
|
||||
@protected
|
||||
double/*!*/ computeMaxIntrinsicWidth(double/*!*/ height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
@ -1556,9 +1622,12 @@ abstract class RenderBox extends RenderObject {
|
|||
/// Do not override this method. Instead, implement
|
||||
/// [computeMinIntrinsicHeight].
|
||||
@mustCallSuper
|
||||
double getMinIntrinsicHeight(double/*!*/ width) {
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
assert(() {
|
||||
if (width == null) {
|
||||
// `width` has a non-nullable return type, but might be null when
|
||||
// running with weak checking, so we need to null check it anyway (and
|
||||
// ignore the warning that the null-handling logic is dead code).
|
||||
if (width == null) { // ignore: dead_code
|
||||
throw FlutterError.fromParts(<DiagnosticsNode>[
|
||||
ErrorSummary('The width argument to getMinIntrinsicHeight was null.'),
|
||||
ErrorDescription('The argument to getMinIntrinsicHeight must not be negative or null.'),
|
||||
|
@ -1612,7 +1681,7 @@ abstract class RenderBox extends RenderObject {
|
|||
/// * [computeMaxIntrinsicHeight], which computes the smallest height beyond
|
||||
/// which increasing the height never decreases the preferred width.
|
||||
@protected
|
||||
double/*!*/ computeMinIntrinsicHeight(double/*!*/ width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
@ -1634,9 +1703,12 @@ abstract class RenderBox extends RenderObject {
|
|||
/// Do not override this method. Instead, implement
|
||||
/// [computeMaxIntrinsicHeight].
|
||||
@mustCallSuper
|
||||
double getMaxIntrinsicHeight(double/*!*/ width) {
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
assert(() {
|
||||
if (width == null) {
|
||||
// `width` has a non-nullable return type, but might be null when
|
||||
// running with weak checking, so we need to null check it anyway (and
|
||||
// ignore the warning that the null-handling logic is dead code).
|
||||
if (width == null) { // ignore: dead_code
|
||||
throw FlutterError.fromParts(<DiagnosticsNode>[
|
||||
ErrorSummary('The width argument to getMaxIntrinsicHeight was null.'),
|
||||
ErrorDescription('The argument to getMaxIntrinsicHeight must not be negative or null.'),
|
||||
|
@ -1692,7 +1764,7 @@ abstract class RenderBox extends RenderObject {
|
|||
///
|
||||
/// * [computeMinIntrinsicWidth], which has usage examples.
|
||||
@protected
|
||||
double/*!*/ computeMaxIntrinsicHeight(double/*!*/ width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
@ -1709,10 +1781,10 @@ abstract class RenderBox extends RenderObject {
|
|||
/// [performResize] functions. If you wish to change the size of a box outside
|
||||
/// of those functions, call [markNeedsLayout] instead to schedule a layout of
|
||||
/// the box.
|
||||
Size/*!*/ get size {
|
||||
Size get size {
|
||||
assert(hasSize, 'RenderBox was not laid out: ${toString()}');
|
||||
assert(() {
|
||||
final Size _size = this._size;
|
||||
final Size? _size = this._size;
|
||||
if (_size is _DebugSize) {
|
||||
assert(_size._owner == this);
|
||||
if (RenderObject.debugActiveLayout != null) {
|
||||
|
@ -1731,14 +1803,14 @@ abstract class RenderBox extends RenderObject {
|
|||
}
|
||||
return true;
|
||||
}());
|
||||
return _size;
|
||||
return _size!;
|
||||
}
|
||||
/*late*/ Size/*!*/ _size;
|
||||
Size? _size;
|
||||
/// Setting the size, in checked mode, triggers some analysis of the render box,
|
||||
/// as implemented by [debugAssertDoesMeetConstraints], including calling the intrinsic
|
||||
/// sizing methods and checking that they meet certain invariants.
|
||||
@protected
|
||||
set size(Size/*!*/ value) {
|
||||
set size(Size value) {
|
||||
assert(!(debugDoingThisResize && debugDoingThisLayout));
|
||||
assert(sizedByParent || !debugDoingThisResize);
|
||||
assert(() {
|
||||
|
@ -1756,7 +1828,7 @@ abstract class RenderBox extends RenderObject {
|
|||
information.add(ErrorDescription(
|
||||
'The size setter was called from outside layout (neither performResize() nor performLayout() were being run for this object).'
|
||||
));
|
||||
if (owner != null && owner.debugDoingLayout)
|
||||
if (owner != null && owner!.debugDoingLayout)
|
||||
information.add(ErrorDescription('Only the object itself can set its size. It is a contract violation for other objects to set it.'));
|
||||
}
|
||||
if (sizedByParent)
|
||||
|
@ -1852,7 +1924,7 @@ abstract class RenderBox extends RenderObject {
|
|||
size = size;
|
||||
}
|
||||
|
||||
Map<TextBaseline/*!*/, double> _cachedBaselines;
|
||||
Map<TextBaseline, double?>? _cachedBaselines;
|
||||
static bool _debugDoingBaseline = false;
|
||||
static bool _debugSetDoingBaseline(bool value) {
|
||||
_debugDoingBaseline = value;
|
||||
|
@ -1875,21 +1947,21 @@ abstract class RenderBox extends RenderObject {
|
|||
///
|
||||
/// When implementing a [RenderBox] subclass, to override the baseline
|
||||
/// computation, override [computeDistanceToActualBaseline].
|
||||
double getDistanceToBaseline(TextBaseline/*!*/ baseline, { bool onlyReal = false }) {
|
||||
double? getDistanceToBaseline(TextBaseline baseline, { bool onlyReal = false }) {
|
||||
assert(!_debugDoingBaseline, 'Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.');
|
||||
assert(!debugNeedsLayout);
|
||||
assert(() {
|
||||
final RenderObject parent = this.parent as RenderObject;
|
||||
if (owner.debugDoingLayout)
|
||||
return (RenderObject.debugActiveLayout == parent) && parent.debugDoingThisLayout;
|
||||
if (owner.debugDoingPaint)
|
||||
return ((RenderObject.debugActivePaint == parent) && parent.debugDoingThisPaint) ||
|
||||
final RenderObject? parent = this.parent as RenderObject?;
|
||||
if (owner!.debugDoingLayout)
|
||||
return (RenderObject.debugActiveLayout == parent) && parent!.debugDoingThisLayout;
|
||||
if (owner!.debugDoingPaint)
|
||||
return ((RenderObject.debugActivePaint == parent) && parent!.debugDoingThisPaint) ||
|
||||
((RenderObject.debugActivePaint == this) && debugDoingThisPaint);
|
||||
assert(parent == this.parent);
|
||||
return false;
|
||||
}());
|
||||
assert(_debugSetDoingBaseline(true));
|
||||
final double result = getDistanceToActualBaseline(baseline);
|
||||
final double? result = getDistanceToActualBaseline(baseline);
|
||||
assert(_debugSetDoingBaseline(false));
|
||||
if (result == null && !onlyReal)
|
||||
return size.height;
|
||||
|
@ -1903,11 +1975,11 @@ abstract class RenderBox extends RenderObject {
|
|||
/// outside those two methods.
|
||||
@protected
|
||||
@mustCallSuper
|
||||
double getDistanceToActualBaseline(TextBaseline/*!*/ baseline) {
|
||||
double? getDistanceToActualBaseline(TextBaseline baseline) {
|
||||
assert(_debugDoingBaseline, 'Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.');
|
||||
_cachedBaselines ??= <TextBaseline, double>{};
|
||||
_cachedBaselines.putIfAbsent(baseline, () => computeDistanceToActualBaseline(baseline));
|
||||
return _cachedBaselines[baseline];
|
||||
_cachedBaselines ??= <TextBaseline, double?>{};
|
||||
_cachedBaselines!.putIfAbsent(baseline, () => computeDistanceToActualBaseline(baseline));
|
||||
return _cachedBaselines![baseline];
|
||||
}
|
||||
|
||||
/// Returns the distance from the y-coordinate of the position of the box to
|
||||
|
@ -1935,7 +2007,7 @@ abstract class RenderBox extends RenderObject {
|
|||
/// [computeDistanceToActualBaseline], the internal implementation, and not
|
||||
/// [getDistanceToBaseline], the public entry point for this API).
|
||||
@protected
|
||||
double computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
double? computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
assert(_debugDoingBaseline, 'Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.');
|
||||
return null;
|
||||
}
|
||||
|
@ -1962,7 +2034,7 @@ abstract class RenderBox extends RenderObject {
|
|||
]);
|
||||
}
|
||||
// verify that the size is not infinite
|
||||
if (!_size.isFinite) {
|
||||
if (!_size!.isFinite) {
|
||||
final List<DiagnosticsNode> information = <DiagnosticsNode>[
|
||||
ErrorSummary('$runtimeType object was given an infinite size during layout.'),
|
||||
ErrorDescription(
|
||||
|
@ -1993,7 +2065,7 @@ abstract class RenderBox extends RenderObject {
|
|||
]);
|
||||
}
|
||||
// verify that the size is within the constraints
|
||||
if (!constraints.isSatisfiedBy(_size)) {
|
||||
if (!constraints.isSatisfiedBy(_size!)) {
|
||||
throw FlutterError.fromParts(<DiagnosticsNode>[
|
||||
ErrorSummary('$runtimeType does not meet its constraints.'),
|
||||
DiagnosticsProperty<BoxConstraints>('Constraints', constraints, style: DiagnosticsTreeStyle.errorProperty),
|
||||
|
@ -2058,8 +2130,8 @@ abstract class RenderBox extends RenderObject {
|
|||
|
||||
@override
|
||||
void markNeedsLayout() {
|
||||
if ((_cachedBaselines != null && _cachedBaselines.isNotEmpty) ||
|
||||
(_cachedIntrinsicDimensions != null && _cachedIntrinsicDimensions.isNotEmpty)) {
|
||||
if ((_cachedBaselines != null && _cachedBaselines!.isNotEmpty) ||
|
||||
(_cachedIntrinsicDimensions != null && _cachedIntrinsicDimensions!.isNotEmpty)) {
|
||||
// If we have cached data, then someone must have used our data.
|
||||
// Since the parent will shortly be marked dirty, we can forget that they
|
||||
// used the baseline and/or intrinsic dimensions. If they use them again,
|
||||
|
@ -2123,7 +2195,7 @@ abstract class RenderBox extends RenderObject {
|
|||
/// called. For example, a render object might be a child of a [RenderOpacity]
|
||||
/// object, which calls [hitTest] on its children when its opacity is zero
|
||||
/// even through it does not [paint] its children.
|
||||
bool hitTest(BoxHitTestResult result, { @required Offset position }) {
|
||||
bool hitTest(BoxHitTestResult result, { required Offset position }) {
|
||||
assert(() {
|
||||
if (!hasSize) {
|
||||
if (debugNeedsLayout) {
|
||||
|
@ -2159,7 +2231,7 @@ abstract class RenderBox extends RenderObject {
|
|||
}
|
||||
return true;
|
||||
}());
|
||||
if (_size.contains(position)) {
|
||||
if (_size!.contains(position)) {
|
||||
if (hitTestChildren(result, position: position) || hitTestSelf(position)) {
|
||||
result.add(BoxHitTestEntry(this, position));
|
||||
return true;
|
||||
|
@ -2208,7 +2280,7 @@ abstract class RenderBox extends RenderObject {
|
|||
/// Used by [hitTest]. If you override [hitTest] and do not call this
|
||||
/// function, then you don't need to implement this function.
|
||||
@protected
|
||||
bool hitTestChildren(BoxHitTestResult result, { Offset position }) => false;
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) => false;
|
||||
|
||||
/// Multiply the transform from the parent's coordinate system to this box's
|
||||
/// coordinate system into the given transform.
|
||||
|
@ -2261,7 +2333,7 @@ abstract class RenderBox extends RenderObject {
|
|||
/// object) instead of from the global coordinate system.
|
||||
///
|
||||
/// This method is implemented in terms of [getTransformTo].
|
||||
Offset globalToLocal(Offset point, { RenderObject ancestor }) {
|
||||
Offset globalToLocal(Offset point, { RenderObject? ancestor }) {
|
||||
// We want to find point (p) that corresponds to a given point on the
|
||||
// screen (s), but that also physically resides on the local render plane,
|
||||
// so that it is useful for visually accurate gesture processing in the
|
||||
|
@ -2296,7 +2368,7 @@ abstract class RenderBox extends RenderObject {
|
|||
/// This method is implemented in terms of [getTransformTo]. If the transform
|
||||
/// matrix puts the given `point` on the line at infinity (for instance, when
|
||||
/// the transform matrix is the zero matrix), this method returns (NaN, NaN).
|
||||
Offset localToGlobal(Offset point, { RenderObject ancestor }) {
|
||||
Offset localToGlobal(Offset point, { RenderObject? ancestor }) {
|
||||
return MatrixUtils.transformPoint(getTransformTo(ancestor), point);
|
||||
}
|
||||
|
||||
|
@ -2408,7 +2480,7 @@ abstract class RenderBox extends RenderObject {
|
|||
..strokeWidth = 0.25;
|
||||
Path path;
|
||||
// ideographic baseline
|
||||
final double baselineI = getDistanceToBaseline(TextBaseline.ideographic, onlyReal: true);
|
||||
final double? baselineI = getDistanceToBaseline(TextBaseline.ideographic, onlyReal: true);
|
||||
if (baselineI != null) {
|
||||
paint.color = const Color(0xFFFFD000);
|
||||
path = Path();
|
||||
|
@ -2417,7 +2489,7 @@ abstract class RenderBox extends RenderObject {
|
|||
context.canvas.drawPath(path, paint);
|
||||
}
|
||||
// alphabetic baseline
|
||||
final double baselineA = getDistanceToBaseline(TextBaseline.alphabetic, onlyReal: true);
|
||||
final double? baselineA = getDistanceToBaseline(TextBaseline.alphabetic, onlyReal: true);
|
||||
if (baselineA != null) {
|
||||
paint.color = const Color(0xFF00FF00);
|
||||
path = Path();
|
||||
|
@ -2466,15 +2538,15 @@ mixin RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, ParentDataTyp
|
|||
///
|
||||
/// Useful when the children are displayed vertically in the same order they
|
||||
/// appear in the child list.
|
||||
double defaultComputeDistanceToFirstActualBaseline(TextBaseline baseline) {
|
||||
double? defaultComputeDistanceToFirstActualBaseline(TextBaseline baseline) {
|
||||
assert(!debugNeedsLayout);
|
||||
ChildType child = firstChild;
|
||||
ChildType? child = firstChild;
|
||||
while (child != null) {
|
||||
final ParentDataType childParentData = child.parentData as ParentDataType;
|
||||
final double result = child.getDistanceToActualBaseline(baseline);
|
||||
final ParentDataType? childParentData = child.parentData as ParentDataType?;
|
||||
final double? result = child.getDistanceToActualBaseline(baseline);
|
||||
if (result != null)
|
||||
return result + childParentData.offset.dy;
|
||||
child = childParentData.nextSibling;
|
||||
return result + childParentData!.offset.dy;
|
||||
child = childParentData!.nextSibling;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -2483,13 +2555,13 @@ mixin RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, ParentDataTyp
|
|||
///
|
||||
/// Useful when the vertical position of the children isn't determined by the
|
||||
/// order in the child list.
|
||||
double defaultComputeDistanceToHighestActualBaseline(TextBaseline baseline) {
|
||||
double? defaultComputeDistanceToHighestActualBaseline(TextBaseline baseline) {
|
||||
assert(!debugNeedsLayout);
|
||||
double result;
|
||||
ChildType child = firstChild;
|
||||
double? result;
|
||||
ChildType? child = firstChild;
|
||||
while (child != null) {
|
||||
final ParentDataType childParentData = child.parentData as ParentDataType;
|
||||
double candidate = child.getDistanceToActualBaseline(baseline);
|
||||
double? candidate = child.getDistanceToActualBaseline(baseline);
|
||||
if (candidate != null) {
|
||||
candidate += childParentData.offset.dy;
|
||||
if (result != null)
|
||||
|
@ -2511,17 +2583,17 @@ mixin RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, ParentDataTyp
|
|||
///
|
||||
/// * [defaultPaint], which paints the children appropriate for this
|
||||
/// hit-testing strategy.
|
||||
bool defaultHitTestChildren(BoxHitTestResult result, { Offset position }) {
|
||||
bool defaultHitTestChildren(BoxHitTestResult result, { required Offset position }) {
|
||||
// The x, y parameters have the top left of the node's box as the origin.
|
||||
ChildType child = lastChild;
|
||||
ChildType? child = lastChild;
|
||||
while (child != null) {
|
||||
final ParentDataType childParentData = child.parentData as ParentDataType;
|
||||
final bool isHit = result.addWithPaintOffset(
|
||||
offset: childParentData.offset,
|
||||
position: position,
|
||||
hitTest: (BoxHitTestResult result, Offset transformed) {
|
||||
hitTest: (BoxHitTestResult result, Offset? transformed) {
|
||||
assert(transformed == position - childParentData.offset);
|
||||
return child.hitTest(result, position: transformed);
|
||||
return child!.hitTest(result, position: transformed!);
|
||||
},
|
||||
);
|
||||
if (isHit)
|
||||
|
@ -2538,7 +2610,7 @@ mixin RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, ParentDataTyp
|
|||
/// * [defaultHitTestChildren], which implements hit-testing of the children
|
||||
/// in a manner appropriate for this painting strategy.
|
||||
void defaultPaint(PaintingContext context, Offset offset) {
|
||||
ChildType child = firstChild;
|
||||
ChildType? child = firstChild;
|
||||
while (child != null) {
|
||||
final ParentDataType childParentData = child.parentData as ParentDataType;
|
||||
context.paintChild(child, childParentData.offset + offset);
|
||||
|
@ -2553,7 +2625,7 @@ mixin RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, ParentDataTyp
|
|||
/// walking the child list directly.
|
||||
List<ChildType> getChildrenAsList() {
|
||||
final List<ChildType> result = <ChildType>[];
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
final ParentDataType childParentData = child.parentData as ParentDataType;
|
||||
result.add(child as ChildType);
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'box.dart';
|
||||
|
@ -14,7 +12,7 @@ import 'object.dart';
|
|||
/// [ParentData] used by [RenderCustomMultiChildLayoutBox].
|
||||
class MultiChildLayoutParentData extends ContainerBoxParentData<RenderBox> {
|
||||
/// An object representing the identity of this child.
|
||||
Object id;
|
||||
Object? id;
|
||||
|
||||
@override
|
||||
String toString() => '${super.toString()}; id=$id';
|
||||
|
@ -120,20 +118,19 @@ abstract class MultiChildLayoutDelegate {
|
|||
/// Creates a layout delegate.
|
||||
///
|
||||
/// The layout will update whenever [relayout] notifies its listeners.
|
||||
MultiChildLayoutDelegate({ Listenable relayout }) : _relayout = relayout;
|
||||
MultiChildLayoutDelegate({ Listenable? relayout }) : _relayout = relayout;
|
||||
|
||||
final Listenable _relayout;
|
||||
final Listenable? _relayout;
|
||||
|
||||
// TODO(ianh): make these late final
|
||||
/*late*/ Map<Object/*!*/, RenderBox>/*!*/ _idToChild;
|
||||
/*late*/ Set<RenderBox/*!*/>/*!*/ _debugChildrenNeedingLayout;
|
||||
Map<Object, RenderBox>? _idToChild;
|
||||
Set<RenderBox>? _debugChildrenNeedingLayout;
|
||||
|
||||
/// True if a non-null LayoutChild was provided for the specified id.
|
||||
///
|
||||
/// Call this from the [performLayout] or [getSize] methods to
|
||||
/// determine which children are available, if the child list might
|
||||
/// vary.
|
||||
bool hasChild(Object childId) => _idToChild[childId] != null;
|
||||
bool hasChild(Object childId) => _idToChild![childId] != null;
|
||||
|
||||
/// Ask the child to update its layout within the limits specified by
|
||||
/// the constraints parameter. The child's size is returned.
|
||||
|
@ -141,8 +138,8 @@ abstract class MultiChildLayoutDelegate {
|
|||
/// Call this from your [performLayout] function to lay out each
|
||||
/// child. Every child must be laid out using this function exactly
|
||||
/// once each time the [performLayout] function is called.
|
||||
Size/*!*/ layoutChild(Object childId, BoxConstraints constraints) {
|
||||
final RenderBox child = _idToChild[childId];
|
||||
Size layoutChild(Object childId, BoxConstraints constraints) {
|
||||
final RenderBox? child = _idToChild![childId];
|
||||
assert(() {
|
||||
if (child == null) {
|
||||
throw FlutterError(
|
||||
|
@ -150,7 +147,7 @@ abstract class MultiChildLayoutDelegate {
|
|||
'There is no child with the id "$childId".'
|
||||
);
|
||||
}
|
||||
if (!_debugChildrenNeedingLayout.remove(child)) {
|
||||
if (!_debugChildrenNeedingLayout!.remove(child)) {
|
||||
throw FlutterError(
|
||||
'The $this custom multichild layout delegate tried to lay out the child with id "$childId" more than once.\n'
|
||||
'Each child must be laid out exactly once.'
|
||||
|
@ -171,7 +168,7 @@ abstract class MultiChildLayoutDelegate {
|
|||
}
|
||||
return true;
|
||||
}());
|
||||
child.layout(constraints, parentUsesSize: true);
|
||||
child!.layout(constraints, parentUsesSize: true);
|
||||
return child.size;
|
||||
}
|
||||
|
||||
|
@ -182,7 +179,7 @@ abstract class MultiChildLayoutDelegate {
|
|||
/// remain unchanged. Children initially have their position set to
|
||||
/// (0,0), i.e. the top left of the [RenderCustomMultiChildLayoutBox].
|
||||
void positionChild(Object childId, Offset offset) {
|
||||
final RenderBox child = _idToChild[childId];
|
||||
final RenderBox? child = _idToChild![childId];
|
||||
assert(() {
|
||||
if (child == null) {
|
||||
throw FlutterError(
|
||||
|
@ -190,14 +187,17 @@ abstract class MultiChildLayoutDelegate {
|
|||
'There is no child with the id "$childId".'
|
||||
);
|
||||
}
|
||||
if (offset == null) {
|
||||
// `offset` has a non-nullable return type, but might be null when
|
||||
// running with weak checking, so we need to null check it anyway (and
|
||||
// ignore the warning that the null-handling logic is dead code).
|
||||
if (offset == null) { // ignore: dead_code
|
||||
throw FlutterError(
|
||||
'The $this custom multichild layout delegate provided a null position for the child with id "$childId".'
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}());
|
||||
final MultiChildLayoutParentData childParentData = child.parentData as MultiChildLayoutParentData;
|
||||
final MultiChildLayoutParentData childParentData = child!.parentData as MultiChildLayoutParentData;
|
||||
childParentData.offset = offset;
|
||||
}
|
||||
|
||||
|
@ -206,14 +206,13 @@ abstract class MultiChildLayoutDelegate {
|
|||
return DiagnosticsProperty<RenderBox>('${childParentData.id}', child);
|
||||
}
|
||||
|
||||
void _callPerformLayout(Size size, RenderBox firstChild) {
|
||||
void _callPerformLayout(Size size, RenderBox? firstChild) {
|
||||
// A particular layout delegate could be called reentrantly, e.g. if it used
|
||||
// by both a parent and a child. So, we must restore the _idToChild map when
|
||||
// we return.
|
||||
final Map<Object, RenderBox> previousIdToChild = _idToChild;
|
||||
final Map<Object, RenderBox>? previousIdToChild = _idToChild;
|
||||
|
||||
// TODO(ianh): make the next line final
|
||||
/*late*/ Set<RenderBox>/*!*/ debugPreviousChildrenNeedingLayout;
|
||||
Set<RenderBox>? debugPreviousChildrenNeedingLayout;
|
||||
assert(() {
|
||||
debugPreviousChildrenNeedingLayout = _debugChildrenNeedingLayout;
|
||||
_debugChildrenNeedingLayout = <RenderBox>{};
|
||||
|
@ -222,36 +221,36 @@ abstract class MultiChildLayoutDelegate {
|
|||
|
||||
try {
|
||||
_idToChild = <Object, RenderBox>{};
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
final MultiChildLayoutParentData childParentData = child.parentData as MultiChildLayoutParentData;
|
||||
assert(() {
|
||||
if (childParentData.id == null) {
|
||||
throw FlutterError.fromParts(<DiagnosticsNode>[
|
||||
ErrorSummary('Every child of a RenderCustomMultiChildLayoutBox must have an ID in its parent data.'),
|
||||
child.describeForError('The following child has no ID'),
|
||||
child!.describeForError('The following child has no ID'),
|
||||
]);
|
||||
}
|
||||
return true;
|
||||
}());
|
||||
_idToChild[childParentData.id] = child;
|
||||
_idToChild![childParentData.id!] = child;
|
||||
assert(() {
|
||||
_debugChildrenNeedingLayout.add(child);
|
||||
_debugChildrenNeedingLayout!.add(child!);
|
||||
return true;
|
||||
}());
|
||||
child = childParentData.nextSibling;
|
||||
}
|
||||
performLayout(size);
|
||||
assert(() {
|
||||
if (_debugChildrenNeedingLayout.isNotEmpty) {
|
||||
if (_debugChildrenNeedingLayout!.isNotEmpty) {
|
||||
throw FlutterError.fromParts(<DiagnosticsNode>[
|
||||
ErrorSummary('Each child must be laid out exactly once.'),
|
||||
DiagnosticsBlock(
|
||||
name:
|
||||
'The $this custom multichild layout delegate forgot '
|
||||
'to lay out the following '
|
||||
'${_debugChildrenNeedingLayout.length > 1 ? 'children' : 'child'}',
|
||||
properties: _debugChildrenNeedingLayout.map<DiagnosticsNode>(_debugDescribeChild).toList(),
|
||||
'${_debugChildrenNeedingLayout!.length > 1 ? 'children' : 'child'}',
|
||||
properties: _debugChildrenNeedingLayout!.map<DiagnosticsNode>(_debugDescribeChild).toList(),
|
||||
style: DiagnosticsTreeStyle.whitespace,
|
||||
),
|
||||
]);
|
||||
|
@ -314,8 +313,8 @@ class RenderCustomMultiChildLayoutBox extends RenderBox
|
|||
///
|
||||
/// The [delegate] argument must not be null.
|
||||
RenderCustomMultiChildLayoutBox({
|
||||
List<RenderBox> children,
|
||||
@required MultiChildLayoutDelegate delegate,
|
||||
List<RenderBox>? children,
|
||||
required MultiChildLayoutDelegate delegate,
|
||||
}) : assert(delegate != null),
|
||||
_delegate = delegate {
|
||||
addAll(children);
|
||||
|
@ -339,20 +338,20 @@ class RenderCustomMultiChildLayoutBox extends RenderBox
|
|||
markNeedsLayout();
|
||||
_delegate = newDelegate;
|
||||
if (attached) {
|
||||
oldDelegate?._relayout?.removeListener(markNeedsLayout);
|
||||
newDelegate?._relayout?.addListener(markNeedsLayout);
|
||||
oldDelegate._relayout?.removeListener(markNeedsLayout);
|
||||
newDelegate._relayout?.addListener(markNeedsLayout);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void attach(PipelineOwner owner) {
|
||||
super.attach(owner);
|
||||
_delegate?._relayout?.addListener(markNeedsLayout);
|
||||
_delegate._relayout?.addListener(markNeedsLayout);
|
||||
}
|
||||
|
||||
@override
|
||||
void detach() {
|
||||
_delegate?._relayout?.removeListener(markNeedsLayout);
|
||||
_delegate._relayout?.removeListener(markNeedsLayout);
|
||||
super.detach();
|
||||
}
|
||||
|
||||
|
@ -409,7 +408,7 @@ class RenderCustomMultiChildLayoutBox extends RenderBox
|
|||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
|
||||
return defaultHitTestChildren(result, position: position);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -134,9 +132,9 @@ abstract class CustomPainter extends Listenable {
|
|||
/// Creates a custom painter.
|
||||
///
|
||||
/// The painter will repaint whenever `repaint` notifies its listeners.
|
||||
const CustomPainter({ Listenable repaint }) : _repaint = repaint;
|
||||
const CustomPainter({ Listenable? repaint }) : _repaint = repaint;
|
||||
|
||||
final Listenable _repaint;
|
||||
final Listenable? _repaint;
|
||||
|
||||
/// Register a closure to be notified when it is time to repaint.
|
||||
///
|
||||
|
@ -203,7 +201,7 @@ abstract class CustomPainter extends Listenable {
|
|||
/// * [SemanticsConfiguration.isSemanticBoundary], which causes new
|
||||
/// [SemanticsNode]s to be added to the semantics tree.
|
||||
/// * [RenderCustomPaint], which uses this getter to build semantics.
|
||||
SemanticsBuilderCallback get semanticsBuilder => null;
|
||||
SemanticsBuilderCallback? get semanticsBuilder => null;
|
||||
|
||||
/// Called whenever a new instance of the custom painter delegate class is
|
||||
/// provided to the [RenderCustomPaint] object, or any time that a new
|
||||
|
@ -267,7 +265,7 @@ abstract class CustomPainter extends Listenable {
|
|||
/// image that should be considered a "hit", false if it corresponds to a
|
||||
/// point that should be considered outside the painted image, and null to use
|
||||
/// the default behavior.
|
||||
bool hitTest(Offset position) => null;
|
||||
bool? hitTest(Offset position) => null;
|
||||
|
||||
@override
|
||||
String toString() => '${describeIdentity(this)}(${ _repaint?.toString() ?? "" })';
|
||||
|
@ -295,8 +293,8 @@ class CustomPainterSemantics {
|
|||
/// Arguments `rect` and `properties` must not be null.
|
||||
const CustomPainterSemantics({
|
||||
this.key,
|
||||
@required this.rect,
|
||||
@required this.properties,
|
||||
required this.rect,
|
||||
required this.properties,
|
||||
this.transform,
|
||||
this.tags,
|
||||
}) : assert(rect != null),
|
||||
|
@ -312,7 +310,7 @@ class CustomPainterSemantics {
|
|||
/// [SemanticsNode] will be updated using this instance.
|
||||
///
|
||||
/// This value is assigned to [SemanticsNode.key] during update.
|
||||
final Key key;
|
||||
final Key? key;
|
||||
|
||||
/// The location and size of the box on the canvas where this piece of semantic
|
||||
/// information applies.
|
||||
|
@ -324,7 +322,7 @@ class CustomPainterSemantics {
|
|||
/// coordinate system.
|
||||
///
|
||||
/// This value is assigned to [SemanticsNode.transform] during update.
|
||||
final Matrix4 transform;
|
||||
final Matrix4? transform;
|
||||
|
||||
/// Contains properties that are assigned to the [SemanticsNode] created or
|
||||
/// updated from this object.
|
||||
|
@ -339,7 +337,7 @@ class CustomPainterSemantics {
|
|||
/// semantics tree.
|
||||
///
|
||||
/// This value is assigned to [SemanticsNode.tags] during update.
|
||||
final Set<SemanticsTag> tags;
|
||||
final Set<SemanticsTag>? tags;
|
||||
}
|
||||
|
||||
/// Provides a canvas on which to draw during the paint phase.
|
||||
|
@ -370,12 +368,12 @@ class CustomPainterSemantics {
|
|||
class RenderCustomPaint extends RenderProxyBox {
|
||||
/// Creates a render object that delegates its painting.
|
||||
RenderCustomPaint({
|
||||
CustomPainter painter,
|
||||
CustomPainter foregroundPainter,
|
||||
CustomPainter? painter,
|
||||
CustomPainter? foregroundPainter,
|
||||
Size preferredSize = Size.zero,
|
||||
this.isComplex = false,
|
||||
this.willChange = false,
|
||||
RenderBox child,
|
||||
RenderBox? child,
|
||||
}) : assert(preferredSize != null),
|
||||
_painter = painter,
|
||||
_foregroundPainter = foregroundPainter,
|
||||
|
@ -385,8 +383,8 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
/// The background custom paint delegate.
|
||||
///
|
||||
/// This painter, if non-null, is called to paint behind the children.
|
||||
CustomPainter get painter => _painter;
|
||||
CustomPainter _painter;
|
||||
CustomPainter? get painter => _painter;
|
||||
CustomPainter? _painter;
|
||||
/// Set a new background custom paint delegate.
|
||||
///
|
||||
/// If the new delegate is the same as the previous one, this does nothing.
|
||||
|
@ -399,10 +397,10 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
/// delegate will be called.
|
||||
///
|
||||
/// If the new value is null, then there is no background custom painter.
|
||||
set painter(CustomPainter value) {
|
||||
set painter(CustomPainter? value) {
|
||||
if (_painter == value)
|
||||
return;
|
||||
final CustomPainter oldPainter = _painter;
|
||||
final CustomPainter? oldPainter = _painter;
|
||||
_painter = value;
|
||||
_didUpdatePainter(_painter, oldPainter);
|
||||
}
|
||||
|
@ -410,8 +408,8 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
/// The foreground custom paint delegate.
|
||||
///
|
||||
/// This painter, if non-null, is called to paint in front of the children.
|
||||
CustomPainter get foregroundPainter => _foregroundPainter;
|
||||
CustomPainter _foregroundPainter;
|
||||
CustomPainter? get foregroundPainter => _foregroundPainter;
|
||||
CustomPainter? _foregroundPainter;
|
||||
/// Set a new foreground custom paint delegate.
|
||||
///
|
||||
/// If the new delegate is the same as the previous one, this does nothing.
|
||||
|
@ -424,15 +422,15 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
/// delegate will be called.
|
||||
///
|
||||
/// If the new value is null, then there is no foreground custom painter.
|
||||
set foregroundPainter(CustomPainter value) {
|
||||
set foregroundPainter(CustomPainter? value) {
|
||||
if (_foregroundPainter == value)
|
||||
return;
|
||||
final CustomPainter oldPainter = _foregroundPainter;
|
||||
final CustomPainter? oldPainter = _foregroundPainter;
|
||||
_foregroundPainter = value;
|
||||
_didUpdatePainter(_foregroundPainter, oldPainter);
|
||||
}
|
||||
|
||||
void _didUpdatePainter(CustomPainter newPainter, CustomPainter oldPainter) {
|
||||
void _didUpdatePainter(CustomPainter? newPainter, CustomPainter? oldPainter) {
|
||||
// Check if we need to repaint.
|
||||
if (newPainter == null) {
|
||||
assert(oldPainter != null); // We should be called only for changes.
|
||||
|
@ -504,15 +502,15 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
|
||||
if (_foregroundPainter != null && (_foregroundPainter.hitTest(position) ?? false))
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
|
||||
if (_foregroundPainter != null && (_foregroundPainter!.hitTest(position) ?? false))
|
||||
return true;
|
||||
return super.hitTestChildren(result, position: position);
|
||||
}
|
||||
|
||||
@override
|
||||
bool hitTestSelf(Offset position) {
|
||||
return _painter != null && (_painter.hitTest(position) ?? true);
|
||||
return _painter != null && (_painter!.hitTest(position) ?? true);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -521,9 +519,8 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
markNeedsSemanticsUpdate();
|
||||
}
|
||||
|
||||
void _paintWithPainter(Canvas canvas, Offset offset, CustomPainter/*!*/ painter) {
|
||||
// TODO(ianh): make the next line final
|
||||
/*late*/ int/*!*/ debugPreviousCanvasSaveCount;
|
||||
void _paintWithPainter(Canvas canvas, Offset offset, CustomPainter painter) {
|
||||
late int debugPreviousCanvasSaveCount;
|
||||
canvas.save();
|
||||
assert(() {
|
||||
debugPreviousCanvasSaveCount = canvas.getSaveCount();
|
||||
|
@ -572,12 +569,12 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
if (_painter != null) {
|
||||
_paintWithPainter(context.canvas, offset, _painter);
|
||||
_paintWithPainter(context.canvas, offset, _painter!);
|
||||
_setRasterCacheHints(context);
|
||||
}
|
||||
super.paint(context, offset);
|
||||
if (_foregroundPainter != null) {
|
||||
_paintWithPainter(context.canvas, offset, _foregroundPainter);
|
||||
_paintWithPainter(context.canvas, offset, _foregroundPainter!);
|
||||
_setRasterCacheHints(context);
|
||||
}
|
||||
}
|
||||
|
@ -590,10 +587,10 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
}
|
||||
|
||||
/// Builds semantics for the picture drawn by [painter].
|
||||
SemanticsBuilderCallback _backgroundSemanticsBuilder;
|
||||
SemanticsBuilderCallback? _backgroundSemanticsBuilder;
|
||||
|
||||
/// Builds semantics for the picture drawn by [foregroundPainter].
|
||||
SemanticsBuilderCallback _foregroundSemanticsBuilder;
|
||||
SemanticsBuilderCallback? _foregroundSemanticsBuilder;
|
||||
|
||||
@override
|
||||
void describeSemanticsConfiguration(SemanticsConfiguration config) {
|
||||
|
@ -604,10 +601,10 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
}
|
||||
|
||||
/// Describe the semantics of the picture painted by the [painter].
|
||||
List<SemanticsNode/*!*/> _backgroundSemanticsNodes;
|
||||
List<SemanticsNode>? _backgroundSemanticsNodes;
|
||||
|
||||
/// Describe the semantics of the picture painted by the [foregroundPainter].
|
||||
List<SemanticsNode/*!*/> _foregroundSemanticsNodes;
|
||||
List<SemanticsNode>? _foregroundSemanticsNodes;
|
||||
|
||||
@override
|
||||
void assembleSemanticsNode(
|
||||
|
@ -628,21 +625,21 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
}());
|
||||
|
||||
final List<CustomPainterSemantics> backgroundSemantics = _backgroundSemanticsBuilder != null
|
||||
? _backgroundSemanticsBuilder(size)
|
||||
? _backgroundSemanticsBuilder!(size)
|
||||
: const <CustomPainterSemantics>[];
|
||||
_backgroundSemanticsNodes = _updateSemanticsChildren(_backgroundSemanticsNodes, backgroundSemantics);
|
||||
|
||||
final List<CustomPainterSemantics> foregroundSemantics = _foregroundSemanticsBuilder != null
|
||||
? _foregroundSemanticsBuilder(size)
|
||||
? _foregroundSemanticsBuilder!(size)
|
||||
: const <CustomPainterSemantics>[];
|
||||
_foregroundSemanticsNodes = _updateSemanticsChildren(_foregroundSemanticsNodes, foregroundSemantics);
|
||||
|
||||
final bool hasBackgroundSemantics = _backgroundSemanticsNodes != null && _backgroundSemanticsNodes.isNotEmpty;
|
||||
final bool hasForegroundSemantics = _foregroundSemanticsNodes != null && _foregroundSemanticsNodes.isNotEmpty;
|
||||
final bool hasBackgroundSemantics = _backgroundSemanticsNodes != null && _backgroundSemanticsNodes!.isNotEmpty;
|
||||
final bool hasForegroundSemantics = _foregroundSemanticsNodes != null && _foregroundSemanticsNodes!.isNotEmpty;
|
||||
final List<SemanticsNode> finalChildren = <SemanticsNode>[
|
||||
if (hasBackgroundSemantics) ..._backgroundSemanticsNodes,
|
||||
if (hasBackgroundSemantics) ..._backgroundSemanticsNodes!,
|
||||
...children,
|
||||
if (hasForegroundSemantics) ..._foregroundSemanticsNodes,
|
||||
if (hasForegroundSemantics) ..._foregroundSemanticsNodes!,
|
||||
];
|
||||
super.assembleSemanticsNode(node, config, finalChildren);
|
||||
}
|
||||
|
@ -676,23 +673,23 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
/// considered because there is only one type of [SemanticsNode]. There is no
|
||||
/// concept of a "forgotten" node in semantics, deactivated nodes, or global
|
||||
/// keys.
|
||||
static List<SemanticsNode/*!*/> _updateSemanticsChildren(
|
||||
List<SemanticsNode> oldSemantics,
|
||||
List<CustomPainterSemantics> newChildSemantics,
|
||||
static List<SemanticsNode> _updateSemanticsChildren(
|
||||
List<SemanticsNode>? oldSemantics,
|
||||
List<CustomPainterSemantics>? newChildSemantics,
|
||||
) {
|
||||
oldSemantics = oldSemantics ?? const <SemanticsNode>[];
|
||||
newChildSemantics = newChildSemantics ?? const <CustomPainterSemantics>[];
|
||||
|
||||
assert(() {
|
||||
final Map<Key/*!*/, int> keys = HashMap<Key/*!*/, int>();
|
||||
final Map<Key, int> keys = HashMap<Key, int>();
|
||||
final List<DiagnosticsNode> information = <DiagnosticsNode>[];
|
||||
for (int i = 0; i < newChildSemantics.length; i += 1) {
|
||||
for (int i = 0; i < newChildSemantics!.length; i += 1) {
|
||||
final CustomPainterSemantics child = newChildSemantics[i];
|
||||
if (child.key != null) {
|
||||
if (keys.containsKey(child.key)) {
|
||||
information.add(ErrorDescription('- duplicate key ${child.key} found at position $i'));
|
||||
}
|
||||
keys[child.key] = i;
|
||||
keys[child.key!] = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -709,7 +706,7 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
int newChildrenBottom = newChildSemantics.length - 1;
|
||||
int oldChildrenBottom = oldSemantics.length - 1;
|
||||
|
||||
final List<SemanticsNode/*!*/> newChildren = List<SemanticsNode/*!*/>(newChildSemantics.length);
|
||||
final List<SemanticsNode?> newChildren = List<SemanticsNode?>.filled(newChildSemantics.length, null, growable: false);
|
||||
|
||||
// Update the top of the list.
|
||||
while ((oldChildrenTop <= oldChildrenBottom) && (newChildrenTop <= newChildrenBottom)) {
|
||||
|
@ -735,23 +732,23 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
|
||||
// Scan the old children in the middle of the list.
|
||||
final bool haveOldChildren = oldChildrenTop <= oldChildrenBottom;
|
||||
Map<Key/*!*/, SemanticsNode> oldKeyedChildren;
|
||||
late final Map<Key, SemanticsNode> oldKeyedChildren;
|
||||
if (haveOldChildren) {
|
||||
oldKeyedChildren = <Key, SemanticsNode>{};
|
||||
while (oldChildrenTop <= oldChildrenBottom) {
|
||||
final SemanticsNode oldChild = oldSemantics[oldChildrenTop];
|
||||
if (oldChild.key != null)
|
||||
oldKeyedChildren[oldChild.key] = oldChild;
|
||||
oldKeyedChildren[oldChild.key!] = oldChild;
|
||||
oldChildrenTop += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the middle of the list.
|
||||
while (newChildrenTop <= newChildrenBottom) {
|
||||
SemanticsNode oldChild;
|
||||
SemanticsNode? oldChild;
|
||||
final CustomPainterSemantics newSemantics = newChildSemantics[newChildrenTop];
|
||||
if (haveOldChildren) {
|
||||
final Key key = newSemantics.key;
|
||||
final Key? key = newSemantics.key;
|
||||
if (key != null) {
|
||||
oldChild = oldKeyedChildren[key];
|
||||
if (oldChild != null) {
|
||||
|
@ -793,13 +790,13 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
}
|
||||
|
||||
assert(() {
|
||||
for (final SemanticsNode node in newChildren) {
|
||||
for (final SemanticsNode? node in newChildren) {
|
||||
assert(node != null);
|
||||
}
|
||||
return true;
|
||||
}());
|
||||
|
||||
return newChildren;
|
||||
return newChildren.cast<SemanticsNode>();
|
||||
}
|
||||
|
||||
/// Whether `oldChild` can be updated with properties from `newSemantics`.
|
||||
|
@ -814,7 +811,7 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
///
|
||||
/// This method requires that `_canUpdateSemanticsChild(oldChild, newSemantics)`
|
||||
/// is true prior to calling it.
|
||||
static SemanticsNode _updateSemanticsChild(SemanticsNode oldChild, CustomPainterSemantics newSemantics) {
|
||||
static SemanticsNode _updateSemanticsChild(SemanticsNode? oldChild, CustomPainterSemantics newSemantics) {
|
||||
assert(oldChild == null || _canUpdateSemanticsChild(oldChild, newSemantics));
|
||||
|
||||
final SemanticsNode newChild = oldChild ?? SemanticsNode(
|
||||
|
@ -830,52 +827,52 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
config.isChecked = properties.checked;
|
||||
}
|
||||
if (properties.selected != null) {
|
||||
config.isSelected = properties.selected;
|
||||
config.isSelected = properties.selected!;
|
||||
}
|
||||
if (properties.button != null) {
|
||||
config.isButton = properties.button;
|
||||
config.isButton = properties.button!;
|
||||
}
|
||||
if (properties.link != null) {
|
||||
config.isLink = properties.link;
|
||||
config.isLink = properties.link!;
|
||||
}
|
||||
if (properties.textField != null) {
|
||||
config.isTextField = properties.textField;
|
||||
config.isTextField = properties.textField!;
|
||||
}
|
||||
if (properties.readOnly != null) {
|
||||
config.isReadOnly = properties.readOnly;
|
||||
config.isReadOnly = properties.readOnly!;
|
||||
}
|
||||
if (properties.focusable != null) {
|
||||
config.isFocusable = properties.focusable;
|
||||
config.isFocusable = properties.focusable!;
|
||||
}
|
||||
if (properties.focused != null) {
|
||||
config.isFocused = properties.focused;
|
||||
config.isFocused = properties.focused!;
|
||||
}
|
||||
if (properties.enabled != null) {
|
||||
config.isEnabled = properties.enabled;
|
||||
}
|
||||
if (properties.inMutuallyExclusiveGroup != null) {
|
||||
config.isInMutuallyExclusiveGroup = properties.inMutuallyExclusiveGroup;
|
||||
config.isInMutuallyExclusiveGroup = properties.inMutuallyExclusiveGroup!;
|
||||
}
|
||||
if (properties.obscured != null) {
|
||||
config.isObscured = properties.obscured;
|
||||
config.isObscured = properties.obscured!;
|
||||
}
|
||||
if (properties.multiline != null) {
|
||||
config.isMultiline = properties.multiline;
|
||||
config.isMultiline = properties.multiline!;
|
||||
}
|
||||
if (properties.hidden != null) {
|
||||
config.isHidden = properties.hidden;
|
||||
config.isHidden = properties.hidden!;
|
||||
}
|
||||
if (properties.header != null) {
|
||||
config.isHeader = properties.header;
|
||||
config.isHeader = properties.header!;
|
||||
}
|
||||
if (properties.scopesRoute != null) {
|
||||
config.scopesRoute = properties.scopesRoute;
|
||||
config.scopesRoute = properties.scopesRoute!;
|
||||
}
|
||||
if (properties.namesRoute != null) {
|
||||
config.namesRoute = properties.namesRoute;
|
||||
config.namesRoute = properties.namesRoute!;
|
||||
}
|
||||
if (properties.liveRegion != null) {
|
||||
config.liveRegion = properties.liveRegion;
|
||||
config.liveRegion = properties.liveRegion!;
|
||||
}
|
||||
if (properties.maxValueLength != null) {
|
||||
config.maxValueLength = properties.maxValueLength;
|
||||
|
@ -887,22 +884,22 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||
config.isToggled = properties.toggled;
|
||||
}
|
||||
if (properties.image != null) {
|
||||
config.isImage = properties.image;
|
||||
config.isImage = properties.image!;
|
||||
}
|
||||
if (properties.label != null) {
|
||||
config.label = properties.label;
|
||||
config.label = properties.label!;
|
||||
}
|
||||
if (properties.value != null) {
|
||||
config.value = properties.value;
|
||||
config.value = properties.value!;
|
||||
}
|
||||
if (properties.increasedValue != null) {
|
||||
config.increasedValue = properties.increasedValue;
|
||||
config.increasedValue = properties.increasedValue!;
|
||||
}
|
||||
if (properties.decreasedValue != null) {
|
||||
config.decreasedValue = properties.decreasedValue;
|
||||
config.decreasedValue = properties.decreasedValue!;
|
||||
}
|
||||
if (properties.hint != null) {
|
||||
config.hint = properties.hint;
|
||||
config.hint = properties.hint!;
|
||||
}
|
||||
if (properties.textDirection != null) {
|
||||
config.textDirection = properties.textDirection;
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/painting.dart';
|
||||
|
||||
|
@ -88,6 +86,11 @@ bool debugRepaintTextRainbowEnabled = false;
|
|||
///
|
||||
/// This check helps developers that want a consistent look and feel detect
|
||||
/// where this inconsistency would occur.
|
||||
///
|
||||
/// This check assumes that elevations on [PhysicalModelLayer] objects have
|
||||
/// been set to non-null values before the scene is built. If this assumption
|
||||
/// is violated, the check will throw exceptions. (The scene building would
|
||||
/// also fail in that case, however.)
|
||||
bool debugCheckElevationsEnabled = false;
|
||||
|
||||
/// The current color to overlay when repainting a layer.
|
||||
|
@ -174,7 +177,7 @@ bool debugProfileLayoutsEnabled = false;
|
|||
bool debugProfilePaintsEnabled = false;
|
||||
|
||||
/// Signature for [debugOnProfilePaint] implementations.
|
||||
typedef ProfilePaintCallback = void Function(RenderObject/*!*/ renderObject);
|
||||
typedef ProfilePaintCallback = void Function(RenderObject renderObject);
|
||||
|
||||
/// Callback invoked for every [RenderObject] painted each frame.
|
||||
///
|
||||
|
@ -190,7 +193,7 @@ typedef ProfilePaintCallback = void Function(RenderObject/*!*/ renderObject);
|
|||
/// callback to generate aggregate profile statistics describing what paints
|
||||
/// occurred when the `ext.flutter.inspector.trackRepaintWidgets` service
|
||||
/// extension is enabled.
|
||||
ProfilePaintCallback debugOnProfilePaint;
|
||||
ProfilePaintCallback? debugOnProfilePaint;
|
||||
|
||||
/// Setting to true will cause all clipping effects from the layer tree to be
|
||||
/// ignored.
|
||||
|
@ -243,7 +246,7 @@ void _debugDrawDoubleRect(Canvas canvas, Rect outerRect, Rect innerRect, Color c
|
|||
///
|
||||
/// Called by [RenderPadding.debugPaintSize] when [debugPaintSizeEnabled] is
|
||||
/// true.
|
||||
void debugPaintPadding(Canvas canvas, Rect outerRect, Rect innerRect, { double outlineWidth = 2.0 }) {
|
||||
void debugPaintPadding(Canvas canvas, Rect outerRect, Rect? innerRect, { double outlineWidth = 2.0 }) {
|
||||
assert(() {
|
||||
if (innerRect != null && !innerRect.isEmpty) {
|
||||
_debugDrawDoubleRect(canvas, outerRect, innerRect, const Color(0x900090FF));
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
|
@ -25,11 +23,11 @@ enum _OverflowSide {
|
|||
// the indicators.
|
||||
class _OverflowRegionData {
|
||||
const _OverflowRegionData({
|
||||
this.rect,
|
||||
required this.rect,
|
||||
this.label = '',
|
||||
this.labelOffset = Offset.zero,
|
||||
this.rotation = 0.0,
|
||||
this.side,
|
||||
required this.side,
|
||||
});
|
||||
|
||||
final Rect rect;
|
||||
|
@ -201,7 +199,7 @@ mixin DebugOverflowIndicatorMixin on RenderObject {
|
|||
return regions;
|
||||
}
|
||||
|
||||
void _reportOverflow(RelativeRect overflow, List<DiagnosticsNode> overflowHints) {
|
||||
void _reportOverflow(RelativeRect overflow, List<DiagnosticsNode>? overflowHints) {
|
||||
overflowHints ??= <DiagnosticsNode>[];
|
||||
if (overflowHints.isEmpty) {
|
||||
overflowHints.add(ErrorDescription(
|
||||
|
@ -248,8 +246,8 @@ mixin DebugOverflowIndicatorMixin on RenderObject {
|
|||
context: ErrorDescription('during layout'),
|
||||
informationCollector: () sync* {
|
||||
if (debugCreator != null)
|
||||
yield DiagnosticsDebugCreator(debugCreator);
|
||||
yield* overflowHints;
|
||||
yield DiagnosticsDebugCreator(debugCreator as Object);
|
||||
yield* overflowHints!;
|
||||
yield describeForError('The specific $runtimeType in question is');
|
||||
// TODO(jacobr): this line is ascii art that it would be nice to
|
||||
// handle a little more generically in GUI debugging clients in the
|
||||
|
@ -271,7 +269,7 @@ mixin DebugOverflowIndicatorMixin on RenderObject {
|
|||
Offset offset,
|
||||
Rect containerRect,
|
||||
Rect childRect, {
|
||||
List<DiagnosticsNode> overflowHints,
|
||||
List<DiagnosticsNode>? overflowHints,
|
||||
}) {
|
||||
final RelativeRect overflow = RelativeRect.fromRect(containerRect, childRect);
|
||||
|
||||
|
@ -285,7 +283,7 @@ mixin DebugOverflowIndicatorMixin on RenderObject {
|
|||
final List<_OverflowRegionData> overflowRegions = _calculateOverflowRegions(overflow, containerRect);
|
||||
for (final _OverflowRegionData region in overflowRegions) {
|
||||
context.canvas.drawRect(region.rect.shift(offset), _indicatorPaint);
|
||||
final TextSpan textSpan = _indicatorLabel[region.side.index].text as TextSpan;
|
||||
final TextSpan? textSpan = _indicatorLabel[region.side.index].text as TextSpan?;
|
||||
if (textSpan?.text != region.label) {
|
||||
_indicatorLabel[region.side.index].text = TextSpan(
|
||||
text: region.label,
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui' as ui show TextBox, lerpDouble, BoxHeightStyle, BoxWidthStyle;
|
||||
|
||||
|
@ -86,7 +84,7 @@ class TextSelectionPoint {
|
|||
final Offset point;
|
||||
|
||||
/// Direction of the text at this edge of the selection.
|
||||
final TextDirection direction;
|
||||
final TextDirection? direction;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
|
@ -95,8 +93,9 @@ class TextSelectionPoint {
|
|||
return '$point-ltr';
|
||||
case TextDirection.rtl:
|
||||
return '$point-rtl';
|
||||
case null:
|
||||
return '$point';
|
||||
}
|
||||
return '$point';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,47 +180,47 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
/// The [offset] is required and must not be null. You can use [new
|
||||
/// ViewportOffset.zero] if you have no need for scrolling.
|
||||
RenderEditable({
|
||||
TextSpan text,
|
||||
@required TextDirection textDirection,
|
||||
TextSpan? text,
|
||||
required TextDirection textDirection,
|
||||
TextAlign textAlign = TextAlign.start,
|
||||
Color cursorColor,
|
||||
Color backgroundCursorColor,
|
||||
ValueNotifier<bool> showCursor,
|
||||
bool hasFocus,
|
||||
@required LayerLink startHandleLayerLink,
|
||||
@required LayerLink endHandleLayerLink,
|
||||
int maxLines = 1,
|
||||
int minLines,
|
||||
Color? cursorColor,
|
||||
Color? backgroundCursorColor,
|
||||
ValueNotifier<bool>? showCursor,
|
||||
bool? hasFocus,
|
||||
required LayerLink startHandleLayerLink,
|
||||
required LayerLink endHandleLayerLink,
|
||||
int? maxLines = 1,
|
||||
int? minLines,
|
||||
bool expands = false,
|
||||
StrutStyle strutStyle,
|
||||
Color selectionColor,
|
||||
StrutStyle? strutStyle,
|
||||
Color? selectionColor,
|
||||
double textScaleFactor = 1.0,
|
||||
TextSelection selection,
|
||||
@required ViewportOffset offset,
|
||||
TextSelection? selection,
|
||||
required ViewportOffset offset,
|
||||
this.onSelectionChanged,
|
||||
this.onCaretChanged,
|
||||
this.ignorePointer = false,
|
||||
bool readOnly = false,
|
||||
bool forceLine = true,
|
||||
TextHeightBehavior textHeightBehavior,
|
||||
TextHeightBehavior? textHeightBehavior,
|
||||
TextWidthBasis textWidthBasis = TextWidthBasis.parent,
|
||||
String obscuringCharacter = '•',
|
||||
bool obscureText = false,
|
||||
Locale locale,
|
||||
Locale? locale,
|
||||
double cursorWidth = 1.0,
|
||||
double cursorHeight,
|
||||
Radius cursorRadius,
|
||||
double? cursorHeight,
|
||||
Radius? cursorRadius,
|
||||
bool paintCursorAboveText = false,
|
||||
Offset cursorOffset,
|
||||
Offset? cursorOffset,
|
||||
double devicePixelRatio = 1.0,
|
||||
ui.BoxHeightStyle selectionHeightStyle = ui.BoxHeightStyle.tight,
|
||||
ui.BoxWidthStyle selectionWidthStyle = ui.BoxWidthStyle.tight,
|
||||
bool enableInteractiveSelection,
|
||||
bool? enableInteractiveSelection,
|
||||
EdgeInsets floatingCursorAddedMargin = const EdgeInsets.fromLTRB(4, 4, 4, 5),
|
||||
TextRange promptRectRange,
|
||||
Color promptRectColor,
|
||||
TextRange? promptRectRange,
|
||||
Color? promptRectColor,
|
||||
Clip clipBehavior = Clip.hardEdge,
|
||||
@required this.textSelectionDelegate,
|
||||
required this.textSelectionDelegate,
|
||||
}) : assert(textAlign != null),
|
||||
assert(textDirection != null, 'RenderEditable created without a textDirection.'),
|
||||
assert(maxLines == null || maxLines > 0),
|
||||
|
@ -300,13 +299,13 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
/// Called when the selection changes.
|
||||
///
|
||||
/// If this is null, then selection changes will be ignored.
|
||||
SelectionChangedHandler onSelectionChanged;
|
||||
SelectionChangedHandler? onSelectionChanged;
|
||||
|
||||
double _textLayoutLastMaxWidth;
|
||||
double _textLayoutLastMinWidth;
|
||||
double? _textLayoutLastMaxWidth;
|
||||
double? _textLayoutLastMinWidth;
|
||||
|
||||
/// Called during the paint phase when the caret location changes.
|
||||
CaretChangedHandler onCaretChanged;
|
||||
CaretChangedHandler? onCaretChanged;
|
||||
|
||||
/// Whether the [handleEvent] will propagate pointer events to selection
|
||||
/// handlers.
|
||||
|
@ -322,8 +321,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
bool ignorePointer;
|
||||
|
||||
/// {@macro flutter.dart:ui.textHeightBehavior}
|
||||
TextHeightBehavior get textHeightBehavior => _textPainter.textHeightBehavior;
|
||||
set textHeightBehavior(TextHeightBehavior value) {
|
||||
TextHeightBehavior? get textHeightBehavior => _textPainter.textHeightBehavior;
|
||||
set textHeightBehavior(TextHeightBehavior? value) {
|
||||
if (_textPainter.textHeightBehavior == value)
|
||||
return;
|
||||
_textPainter.textHeightBehavior = value;
|
||||
|
@ -383,7 +382,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
/// with the most recently set [TextSelectionDelegate].
|
||||
TextSelectionDelegate textSelectionDelegate;
|
||||
|
||||
Rect _lastCaretRect;
|
||||
Rect? _lastCaretRect;
|
||||
|
||||
/// Track whether position of the start of the selected text is within the viewport.
|
||||
///
|
||||
|
@ -416,7 +415,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
final Rect visibleRegion = Offset.zero & size;
|
||||
|
||||
final Offset startOffset = _textPainter.getOffsetForCaret(
|
||||
TextPosition(offset: selection.start, affinity: selection.affinity),
|
||||
TextPosition(offset: selection!.start, affinity: selection!.affinity),
|
||||
_caretPrototype,
|
||||
);
|
||||
// TODO(justinmc): https://github.com/flutter/flutter/issues/31495
|
||||
|
@ -432,7 +431,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
.contains(startOffset + effectiveOffset);
|
||||
|
||||
final Offset endOffset = _textPainter.getOffsetForCaret(
|
||||
TextPosition(offset: selection.end, affinity: selection.affinity),
|
||||
TextPosition(offset: selection!.end, affinity: selection!.affinity),
|
||||
_caretPrototype,
|
||||
);
|
||||
_selectionEndInViewport.value = visibleRegion
|
||||
|
@ -468,7 +467,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
return;
|
||||
}
|
||||
if (onSelectionChanged != null) {
|
||||
onSelectionChanged(nextSelection, this, cause);
|
||||
onSelectionChanged!(nextSelection, this, cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -600,7 +599,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
}
|
||||
|
||||
int count = 0;
|
||||
int lastNonWhitespace;
|
||||
int? lastNonWhitespace;
|
||||
for (final String currentString in string.characters) {
|
||||
if (!includeWhitespace &&
|
||||
!_isWhitespace(currentString.characters.first.toString().codeUnitAt(0))) {
|
||||
|
@ -616,17 +615,17 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
|
||||
void _handleMovement(
|
||||
LogicalKeyboardKey key, {
|
||||
@required bool wordModifier,
|
||||
@required bool lineModifier,
|
||||
@required bool shift,
|
||||
}) {
|
||||
required bool wordModifier,
|
||||
required bool lineModifier,
|
||||
required bool shift,
|
||||
}){
|
||||
if (wordModifier && lineModifier) {
|
||||
// If both modifiers are down, nothing happens on any of the platforms.
|
||||
return;
|
||||
}
|
||||
assert(selection != null);
|
||||
|
||||
TextSelection/*!*/ newSelection = selection;
|
||||
TextSelection newSelection = selection!;
|
||||
|
||||
final bool rightArrow = key == LogicalKeyboardKey.arrowRight;
|
||||
final bool leftArrow = key == LogicalKeyboardKey.arrowLeft;
|
||||
|
@ -734,7 +733,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
// We want to put the cursor at the correct location depending on which
|
||||
// arrow is used while there is a selection.
|
||||
int newOffset = newSelection.extentOffset;
|
||||
if (!selection.isCollapsed) {
|
||||
if (!selection!.isCollapsed) {
|
||||
if (leftArrow) {
|
||||
newOffset = newSelection.baseOffset < newSelection.extentOffset ? newSelection.baseOffset : newSelection.extentOffset;
|
||||
} else if (rightArrow) {
|
||||
|
@ -758,19 +757,19 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
assert(selection != null);
|
||||
assert(_shortcutKeys.contains(key), 'shortcut key $key not recognized.');
|
||||
if (key == LogicalKeyboardKey.keyC) {
|
||||
if (!selection.isCollapsed) {
|
||||
if (!selection!.isCollapsed) {
|
||||
Clipboard.setData(
|
||||
ClipboardData(text: selection.textInside(_plainText)));
|
||||
ClipboardData(text: selection!.textInside(_plainText)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (key == LogicalKeyboardKey.keyX) {
|
||||
if (!selection.isCollapsed) {
|
||||
Clipboard.setData(ClipboardData(text: selection.textInside(_plainText)));
|
||||
if (!selection!.isCollapsed) {
|
||||
Clipboard.setData(ClipboardData(text: selection!.textInside(_plainText)));
|
||||
textSelectionDelegate.textEditingValue = TextEditingValue(
|
||||
text: selection.textBefore(_plainText)
|
||||
+ selection.textAfter(_plainText),
|
||||
selection: TextSelection.collapsed(offset: selection.start),
|
||||
text: selection!.textBefore(_plainText)
|
||||
+ selection!.textAfter(_plainText),
|
||||
selection: TextSelection.collapsed(offset: selection!.start),
|
||||
);
|
||||
}
|
||||
return;
|
||||
|
@ -779,14 +778,14 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
// Snapshot the input before using `await`.
|
||||
// See https://github.com/flutter/flutter/issues/11427
|
||||
final TextEditingValue value = textSelectionDelegate.textEditingValue;
|
||||
final ClipboardData data = await Clipboard.getData(Clipboard.kTextPlain);
|
||||
final ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain);
|
||||
if (data != null) {
|
||||
textSelectionDelegate.textEditingValue = TextEditingValue(
|
||||
text: value.selection.textBefore(value.text)
|
||||
+ data.text
|
||||
+ data.text!
|
||||
+ value.selection.textAfter(value.text),
|
||||
selection: TextSelection.collapsed(
|
||||
offset: value.selection.start + data.text.length
|
||||
offset: value.selection.start + data.text!.length
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -794,7 +793,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
}
|
||||
if (key == LogicalKeyboardKey.keyA) {
|
||||
_handleSelectionChange(
|
||||
selection.copyWith(
|
||||
selection!.copyWith(
|
||||
baseOffset: 0,
|
||||
extentOffset: textSelectionDelegate.textEditingValue.text.length,
|
||||
),
|
||||
|
@ -806,18 +805,18 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
|
||||
void _handleDelete() {
|
||||
assert(_selection != null);
|
||||
final String textAfter = selection.textAfter(_plainText);
|
||||
final String textAfter = selection!.textAfter(_plainText);
|
||||
if (textAfter.isNotEmpty) {
|
||||
final int deleteCount = nextCharacter(0, textAfter);
|
||||
textSelectionDelegate.textEditingValue = TextEditingValue(
|
||||
text: selection.textBefore(_plainText)
|
||||
+ selection.textAfter(_plainText).substring(deleteCount),
|
||||
selection: TextSelection.collapsed(offset: selection.start),
|
||||
text: selection!.textBefore(_plainText)
|
||||
+ selection!.textAfter(_plainText).substring(deleteCount),
|
||||
selection: TextSelection.collapsed(offset: selection!.start),
|
||||
);
|
||||
} else {
|
||||
textSelectionDelegate.textEditingValue = TextEditingValue(
|
||||
text: selection.textBefore(_plainText),
|
||||
selection: TextSelection.collapsed(offset: selection.start),
|
||||
text: selection!.textBefore(_plainText),
|
||||
selection: TextSelection.collapsed(offset: selection!.start),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -842,16 +841,16 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
}
|
||||
|
||||
// Returns a cached plain text version of the text in the painter.
|
||||
String _cachedPlainText;
|
||||
String/*!*/ get _plainText {
|
||||
_cachedPlainText ??= _textPainter.text.toPlainText();
|
||||
return _cachedPlainText;
|
||||
String? _cachedPlainText;
|
||||
String get _plainText {
|
||||
_cachedPlainText ??= _textPainter.text!.toPlainText();
|
||||
return _cachedPlainText!;
|
||||
}
|
||||
|
||||
/// The text to display.
|
||||
TextSpan get text => _textPainter.text as TextSpan;
|
||||
TextSpan? get text => _textPainter.text as TextSpan?;
|
||||
final TextPainter _textPainter;
|
||||
set text(TextSpan/*?*/ value) {
|
||||
set text(TextSpan? value) {
|
||||
if (_textPainter.text == value)
|
||||
return;
|
||||
_textPainter.text = value;
|
||||
|
@ -888,7 +887,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
// TextPainter.textDirection is nullable, but it is set to a
|
||||
// non-null value in the RenderEditable constructor and we refuse to
|
||||
// set it to null here, so _textPainter.textDirection cannot be null.
|
||||
TextDirection get textDirection => _textPainter.textDirection/*!*/;
|
||||
TextDirection get textDirection => _textPainter.textDirection!;
|
||||
set textDirection(TextDirection value) {
|
||||
assert(value != null);
|
||||
if (_textPainter.textDirection == value)
|
||||
|
@ -908,8 +907,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
///
|
||||
/// If this value is null, a system-dependent algorithm is used to select
|
||||
/// the font.
|
||||
Locale get locale => _textPainter.locale;
|
||||
set locale(Locale value) {
|
||||
Locale? get locale => _textPainter.locale;
|
||||
set locale(Locale? value) {
|
||||
if (_textPainter.locale == value)
|
||||
return;
|
||||
_textPainter.locale = value;
|
||||
|
@ -918,8 +917,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
|
||||
/// The [StrutStyle] used by the renderer's internal [TextPainter] to
|
||||
/// determine the strut to use.
|
||||
StrutStyle get strutStyle => _textPainter.strutStyle;
|
||||
set strutStyle(StrutStyle value) {
|
||||
StrutStyle? get strutStyle => _textPainter.strutStyle;
|
||||
set strutStyle(StrutStyle? value) {
|
||||
if (_textPainter.strutStyle == value)
|
||||
return;
|
||||
_textPainter.strutStyle = value;
|
||||
|
@ -927,9 +926,9 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
}
|
||||
|
||||
/// The color to use when painting the cursor.
|
||||
Color get cursorColor => _cursorColor;
|
||||
Color _cursorColor;
|
||||
set cursorColor(Color value) {
|
||||
Color? get cursorColor => _cursorColor;
|
||||
Color? _cursorColor;
|
||||
set cursorColor(Color? value) {
|
||||
if (_cursorColor == value)
|
||||
return;
|
||||
_cursorColor = value;
|
||||
|
@ -940,9 +939,9 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
/// rendering the floating cursor.
|
||||
///
|
||||
/// The default is light grey.
|
||||
Color get backgroundCursorColor => _backgroundCursorColor;
|
||||
Color _backgroundCursorColor;
|
||||
set backgroundCursorColor(Color value) {
|
||||
Color? get backgroundCursorColor => _backgroundCursorColor;
|
||||
Color? _backgroundCursorColor;
|
||||
set backgroundCursorColor(Color? value) {
|
||||
if (backgroundCursorColor == value)
|
||||
return;
|
||||
_backgroundCursorColor = value;
|
||||
|
@ -1017,10 +1016,10 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
/// When this is not null, the intrinsic height of the render object is the
|
||||
/// height of one line of text multiplied by this value. In other words, this
|
||||
/// also controls the height of the actual editing widget.
|
||||
int get maxLines => _maxLines;
|
||||
int _maxLines;
|
||||
int? get maxLines => _maxLines;
|
||||
int? _maxLines;
|
||||
/// The value may be null. If it is not null, then it must be greater than zero.
|
||||
set maxLines(int value) {
|
||||
set maxLines(int? value) {
|
||||
assert(value == null || value > 0);
|
||||
if (maxLines == value)
|
||||
return;
|
||||
|
@ -1029,10 +1028,10 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
}
|
||||
|
||||
/// {@macro flutter.widgets.editableText.minLines}
|
||||
int get minLines => _minLines;
|
||||
int _minLines;
|
||||
int? get minLines => _minLines;
|
||||
int? _minLines;
|
||||
/// The value may be null. If it is not null, then it must be greater than zero.
|
||||
set minLines(int value) {
|
||||
set minLines(int? value) {
|
||||
assert(value == null || value > 0);
|
||||
if (minLines == value)
|
||||
return;
|
||||
|
@ -1052,9 +1051,9 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
}
|
||||
|
||||
/// The color to use when painting the selection.
|
||||
Color get selectionColor => _selectionColor;
|
||||
Color _selectionColor;
|
||||
set selectionColor(Color value) {
|
||||
Color? get selectionColor => _selectionColor;
|
||||
Color? _selectionColor;
|
||||
set selectionColor(Color? value) {
|
||||
if (_selectionColor == value)
|
||||
return;
|
||||
_selectionColor = value;
|
||||
|
@ -1074,7 +1073,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
markNeedsTextLayout();
|
||||
}
|
||||
|
||||
List<ui.TextBox> _selectionRects;
|
||||
List<ui.TextBox>? _selectionRects;
|
||||
|
||||
/// The region of text that is selected, if any.
|
||||
///
|
||||
|
@ -1082,9 +1081,9 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
///
|
||||
/// If [selection] is null, there is no selection and attempts to
|
||||
/// manipulate the selection will throw.
|
||||
TextSelection get selection => _selection;
|
||||
TextSelection _selection;
|
||||
set selection(TextSelection value) {
|
||||
TextSelection? get selection => _selection;
|
||||
TextSelection? _selection;
|
||||
set selection(TextSelection? value) {
|
||||
if (_selection == value)
|
||||
return;
|
||||
_selection = value;
|
||||
|
@ -1123,9 +1122,15 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
}
|
||||
|
||||
/// How tall the cursor will be.
|
||||
///
|
||||
/// This can be null, in which case the getter will actually return [preferredLineHeight].
|
||||
///
|
||||
/// Setting this to itself fixes the value to the current [preferredLineHeight]. Setting
|
||||
/// this to null returns the behaviour of deferring to [preferredLineHeight].
|
||||
// TODO(ianh): This is a confusing API. We should have a separate getter for the effective cursor height.
|
||||
double get cursorHeight => _cursorHeight ?? preferredLineHeight;
|
||||
double _cursorHeight;
|
||||
set cursorHeight(double value) {
|
||||
double? _cursorHeight;
|
||||
set cursorHeight(double? value) {
|
||||
if (_cursorHeight == value)
|
||||
return;
|
||||
_cursorHeight = value;
|
||||
|
@ -1155,9 +1160,9 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
/// platforms. The origin from where the offset is applied to is the arbitrary
|
||||
/// location where the cursor ends up being rendered from by default.
|
||||
/// {@endtemplate}
|
||||
Offset get cursorOffset => _cursorOffset;
|
||||
Offset _cursorOffset;
|
||||
set cursorOffset(Offset value) {
|
||||
Offset? get cursorOffset => _cursorOffset;
|
||||
Offset? _cursorOffset;
|
||||
set cursorOffset(Offset? value) {
|
||||
if (_cursorOffset == value)
|
||||
return;
|
||||
_cursorOffset = value;
|
||||
|
@ -1165,9 +1170,11 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
}
|
||||
|
||||
/// How rounded the corners of the cursor should be.
|
||||
Radius get cursorRadius => _cursorRadius;
|
||||
Radius _cursorRadius;
|
||||
set cursorRadius(Radius value) {
|
||||
///
|
||||
/// A null value is the same as [Radius.zero].
|
||||
Radius? get cursorRadius => _cursorRadius;
|
||||
Radius? _cursorRadius;
|
||||
set cursorRadius(Radius? value) {
|
||||
if (_cursorRadius == value)
|
||||
return;
|
||||
_cursorRadius = value;
|
||||
|
@ -1214,8 +1221,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
}
|
||||
|
||||
bool _floatingCursorOn = false;
|
||||
Offset _floatingCursorOffset;
|
||||
TextPosition _floatingCursorTextPosition;
|
||||
late Offset _floatingCursorOffset;
|
||||
late TextPosition _floatingCursorTextPosition;
|
||||
|
||||
/// Controls how tall the selection highlight boxes are computed to be.
|
||||
///
|
||||
|
@ -1256,9 +1263,9 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
/// the accessibility hints mentioned above). When null,
|
||||
/// [obscureText] is used to determine the value of
|
||||
/// [selectionEnabled] instead.
|
||||
bool get enableInteractiveSelection => _enableInteractiveSelection;
|
||||
bool _enableInteractiveSelection;
|
||||
set enableInteractiveSelection(bool/*?*/ value) {
|
||||
bool? get enableInteractiveSelection => _enableInteractiveSelection;
|
||||
bool? _enableInteractiveSelection;
|
||||
set enableInteractiveSelection(bool? value) {
|
||||
if (_enableInteractiveSelection == value)
|
||||
return;
|
||||
_enableInteractiveSelection = value;
|
||||
|
@ -1296,8 +1303,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
// TODO(ianh): We should change the getter to return null when _promptRectRange is null
|
||||
// (otherwise, if you set it to null and then get it, you get back non-null).
|
||||
// Alternatively, we could stop supporting setting this to null.
|
||||
Color/*?*/ get promptRectColor => _promptRectPaint.color;
|
||||
set promptRectColor(Color/*?*/ newValue) {
|
||||
Color? get promptRectColor => _promptRectPaint.color;
|
||||
set promptRectColor(Color? newValue) {
|
||||
// Painter.color cannot be null.
|
||||
if (newValue == null) {
|
||||
setPromptRectRange(null);
|
||||
|
@ -1312,14 +1319,14 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
markNeedsPaint();
|
||||
}
|
||||
|
||||
TextRange _promptRectRange;
|
||||
TextRange? _promptRectRange;
|
||||
/// Dismisses the currently displayed prompt rectangle and displays a new prompt rectangle
|
||||
/// over [newRange] in the given color [promptRectColor].
|
||||
///
|
||||
/// The prompt rectangle will only be requested on non-web iOS applications.
|
||||
///
|
||||
/// When set to null, the currently displayed prompt rectangle (if any) will be dismissed.
|
||||
void setPromptRectRange(TextRange/*?*/ newRange) {
|
||||
void setPromptRectRange(TextRange? newRange) {
|
||||
if (_promptRectRange == newRange)
|
||||
return;
|
||||
|
||||
|
@ -1333,7 +1340,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
/// text is entered or removed in order to accommodate expanding when
|
||||
/// [expands] is set to true.
|
||||
double get maxScrollExtent => _maxScrollExtent;
|
||||
double/*!*/ _maxScrollExtent = 0;
|
||||
double _maxScrollExtent = 0;
|
||||
|
||||
double get _caretMargin => _kCaretGap + cursorWidth;
|
||||
|
||||
|
@ -1371,12 +1378,12 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
|
||||
if (selectionEnabled && selection?.isValid == true) {
|
||||
config.textSelection = selection;
|
||||
if (_textPainter.getOffsetBefore(selection.extentOffset) != null) {
|
||||
if (_textPainter.getOffsetBefore(selection!.extentOffset) != null) {
|
||||
config
|
||||
..onMoveCursorBackwardByWord = _handleMoveCursorBackwardByWord
|
||||
..onMoveCursorBackwardByCharacter = _handleMoveCursorBackwardByCharacter;
|
||||
}
|
||||
if (_textPainter.getOffsetAfter(selection.extentOffset) != null) {
|
||||
if (_textPainter.getOffsetAfter(selection!.extentOffset) != null) {
|
||||
config
|
||||
..onMoveCursorForwardByWord = _handleMoveCursorForwardByWord
|
||||
..onMoveCursorForwardByCharacter = _handleMoveCursorForwardByCharacter;
|
||||
|
@ -1394,10 +1401,10 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
|
||||
void _handleMoveCursorForwardByCharacter(bool extentSelection) {
|
||||
assert(selection != null);
|
||||
final int extentOffset = _textPainter.getOffsetAfter(selection.extentOffset);
|
||||
final int? extentOffset = _textPainter.getOffsetAfter(selection!.extentOffset);
|
||||
if (extentOffset == null)
|
||||
return;
|
||||
final int baseOffset = !extentSelection ? extentOffset : selection.baseOffset;
|
||||
final int baseOffset = !extentSelection ? extentOffset : selection!.baseOffset;
|
||||
_handleSelectionChange(
|
||||
TextSelection(baseOffset: baseOffset, extentOffset: extentOffset), SelectionChangedCause.keyboard,
|
||||
);
|
||||
|
@ -1405,10 +1412,10 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
|
||||
void _handleMoveCursorBackwardByCharacter(bool extentSelection) {
|
||||
assert(selection != null);
|
||||
final int extentOffset = _textPainter.getOffsetBefore(selection.extentOffset);
|
||||
final int? extentOffset = _textPainter.getOffsetBefore(selection!.extentOffset);
|
||||
if (extentOffset == null)
|
||||
return;
|
||||
final int baseOffset = !extentSelection ? extentOffset : selection.baseOffset;
|
||||
final int baseOffset = !extentSelection ? extentOffset : selection!.baseOffset;
|
||||
_handleSelectionChange(
|
||||
TextSelection(baseOffset: baseOffset, extentOffset: extentOffset), SelectionChangedCause.keyboard,
|
||||
);
|
||||
|
@ -1416,13 +1423,11 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
|
||||
void _handleMoveCursorForwardByWord(bool extentSelection) {
|
||||
assert(selection != null);
|
||||
final TextRange currentWord = _textPainter.getWordBoundary(selection.extent);
|
||||
if (currentWord == null)
|
||||
return;
|
||||
final TextRange nextWord = _getNextWord(currentWord.end);
|
||||
final TextRange currentWord = _textPainter.getWordBoundary(selection!.extent);
|
||||
final TextRange? nextWord = _getNextWord(currentWord.end);
|
||||
if (nextWord == null)
|
||||
return;
|
||||
final int baseOffset = extentSelection ? selection.baseOffset : nextWord.start;
|
||||
final int baseOffset = extentSelection ? selection!.baseOffset : nextWord.start;
|
||||
_handleSelectionChange(
|
||||
TextSelection(
|
||||
baseOffset: baseOffset,
|
||||
|
@ -1434,13 +1439,11 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
|
||||
void _handleMoveCursorBackwardByWord(bool extentSelection) {
|
||||
assert(selection != null);
|
||||
final TextRange currentWord = _textPainter.getWordBoundary(selection.extent);
|
||||
if (currentWord == null)
|
||||
return;
|
||||
final TextRange previousWord = _getPreviousWord(currentWord.start - 1);
|
||||
final TextRange currentWord = _textPainter.getWordBoundary(selection!.extent);
|
||||
final TextRange? previousWord = _getPreviousWord(currentWord.start - 1);
|
||||
if (previousWord == null)
|
||||
return;
|
||||
final int baseOffset = extentSelection ? selection.baseOffset : previousWord.start;
|
||||
final int baseOffset = extentSelection ? selection!.baseOffset : previousWord.start;
|
||||
_handleSelectionChange(
|
||||
TextSelection(
|
||||
baseOffset: baseOffset,
|
||||
|
@ -1450,7 +1453,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
);
|
||||
}
|
||||
|
||||
TextRange _getNextWord(int offset) {
|
||||
TextRange? _getNextWord(int offset) {
|
||||
while (true) {
|
||||
final TextRange range = _textPainter.getWordBoundary(TextPosition(offset: offset));
|
||||
if (range == null || !range.isValid || range.isCollapsed)
|
||||
|
@ -1461,7 +1464,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
}
|
||||
}
|
||||
|
||||
TextRange _getPreviousWord(int offset) {
|
||||
TextRange? _getPreviousWord(int offset) {
|
||||
while (offset >= 0) {
|
||||
final TextRange range = _textPainter.getWordBoundary(TextPosition(offset: offset));
|
||||
if (range == null || !range.isValid || range.isCollapsed)
|
||||
|
@ -1481,7 +1484,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
// TODO(jonahwilliams): replace when we expose this ICU information.
|
||||
bool _onlyWhitespace(TextRange range) {
|
||||
for (int i = range.start; i < range.end; i++) {
|
||||
final int/*!*/ codeUnit = text.codeUnitAt(i);
|
||||
final int codeUnit = text!.codeUnitAt(i)!;
|
||||
if (!_isWhitespace(codeUnit)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1515,17 +1518,16 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
|
||||
Axis get _viewportAxis => _isMultiline ? Axis.vertical : Axis.horizontal;
|
||||
|
||||
Offset/*!*/ get _paintOffset {
|
||||
Offset get _paintOffset {
|
||||
switch (_viewportAxis) {
|
||||
case Axis.horizontal:
|
||||
return Offset(-offset.pixels, 0.0);
|
||||
case Axis.vertical:
|
||||
return Offset(0.0, -offset.pixels);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
double/*!*/ get _viewportExtent {
|
||||
double get _viewportExtent {
|
||||
assert(hasSize);
|
||||
switch (_viewportAxis) {
|
||||
case Axis.horizontal:
|
||||
|
@ -1533,10 +1535,9 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
case Axis.vertical:
|
||||
return size.height;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
double/*!*/ _getMaxScrollExtent(Size contentSize) {
|
||||
double _getMaxScrollExtent(Size contentSize) {
|
||||
assert(hasSize);
|
||||
switch (_viewportAxis) {
|
||||
case Axis.horizontal:
|
||||
|
@ -1544,7 +1545,6 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
case Axis.vertical:
|
||||
return math.max(0.0, contentSize.height - size.height);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// We need to check the paint offset here because during animation, the start of
|
||||
|
@ -1619,7 +1619,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
Rect rect = Rect.fromLTWH(0.0, 0.0, cursorWidth, cursorHeight).shift(caretOffset + _paintOffset);
|
||||
// Add additional cursor offset (generally only if on iOS).
|
||||
if (_cursorOffset != null)
|
||||
rect = rect.shift(_cursorOffset);
|
||||
rect = rect.shift(_cursorOffset!);
|
||||
|
||||
return rect.shift(_getPixelPerfectCursorOffset(rect));
|
||||
}
|
||||
|
@ -1646,19 +1646,19 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
final bool lockedBoth = minLines != null && minLines == maxLines;
|
||||
final bool singleLine = maxLines == 1;
|
||||
if (singleLine || lockedMax || lockedBoth) {
|
||||
return preferredLineHeight * maxLines;
|
||||
return preferredLineHeight * maxLines!;
|
||||
}
|
||||
|
||||
// Clamp height to minLines or maxLines if needed.
|
||||
final bool minLimited = minLines != null && minLines > 1;
|
||||
final bool minLimited = minLines != null && minLines! > 1;
|
||||
final bool maxLimited = maxLines != null;
|
||||
if (minLimited || maxLimited) {
|
||||
_layoutText(maxWidth: width);
|
||||
if (minLimited && _textPainter.height < preferredLineHeight * minLines) {
|
||||
return preferredLineHeight * minLines;
|
||||
if (minLimited && _textPainter.height < preferredLineHeight * minLines!) {
|
||||
return preferredLineHeight * minLines!;
|
||||
}
|
||||
if (maxLimited && _textPainter.height > preferredLineHeight * maxLines) {
|
||||
return preferredLineHeight * maxLines;
|
||||
if (maxLimited && _textPainter.height > preferredLineHeight * maxLines!) {
|
||||
return preferredLineHeight * maxLines!;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1695,8 +1695,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
@override
|
||||
bool hitTestSelf(Offset position) => true;
|
||||
|
||||
TapGestureRecognizer _tap;
|
||||
LongPressGestureRecognizer _longPress;
|
||||
late TapGestureRecognizer _tap;
|
||||
late LongPressGestureRecognizer _longPress;
|
||||
|
||||
@override
|
||||
void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
|
||||
|
@ -1706,7 +1706,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
// Checks if there is any gesture recognizer in the text span.
|
||||
final Offset offset = entry.localPosition;
|
||||
final TextPosition position = _textPainter.getPositionForOffset(offset);
|
||||
final InlineSpan span = _textPainter.text.getSpanForPosition(position);
|
||||
final InlineSpan? span = _textPainter.text!.getSpanForPosition(position);
|
||||
if (span != null && span is TextSpan) {
|
||||
final TextSpan textSpan = span;
|
||||
textSpan.recognizer?.addPointer(event);
|
||||
|
@ -1720,7 +1720,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
}
|
||||
}
|
||||
|
||||
Offset _lastTapDownPosition;
|
||||
Offset? _lastTapDownPosition;
|
||||
|
||||
/// If [ignorePointer] is false (the default) then this method is called by
|
||||
/// the internal gesture recognizer's [TapGestureRecognizer.onTapDown]
|
||||
|
@ -1784,12 +1784,12 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
/// If you have a [TextEditingController], it's generally easier to
|
||||
/// programmatically manipulate its `value` or `selection` directly.
|
||||
/// {@endtemplate}
|
||||
void selectPosition({ @required SelectionChangedCause cause }) {
|
||||
selectPositionAt(from: _lastTapDownPosition, cause: cause);
|
||||
void selectPosition({ required SelectionChangedCause cause }) {
|
||||
selectPositionAt(from: _lastTapDownPosition!, cause: cause);
|
||||
}
|
||||
|
||||
/// Select text between the global positions [from] and [to].
|
||||
void selectPositionAt({ @required Offset from, Offset to, @required SelectionChangedCause cause }) {
|
||||
void selectPositionAt({ required Offset from, Offset? to, required SelectionChangedCause cause }) {
|
||||
assert(cause != null);
|
||||
assert(from != null);
|
||||
_layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
|
||||
|
@ -1797,7 +1797,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
return;
|
||||
}
|
||||
final TextPosition fromPosition = _textPainter.getPositionForOffset(globalToLocal(from - _paintOffset));
|
||||
final TextPosition toPosition = to == null
|
||||
final TextPosition? toPosition = to == null
|
||||
? null
|
||||
: _textPainter.getPositionForOffset(globalToLocal(to - _paintOffset));
|
||||
|
||||
|
@ -1820,8 +1820,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
/// Select a word around the location of the last tap down.
|
||||
///
|
||||
/// {@macro flutter.rendering.editable.select}
|
||||
void selectWord({ @required SelectionChangedCause cause }) {
|
||||
selectWordsInRange(from: _lastTapDownPosition, cause: cause);
|
||||
void selectWord({ required SelectionChangedCause cause }) {
|
||||
selectWordsInRange(from: _lastTapDownPosition!, cause: cause);
|
||||
}
|
||||
|
||||
/// Selects the set words of a paragraph in a given range of global positions.
|
||||
|
@ -1830,7 +1830,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
/// beginning and end of a word respectively.
|
||||
///
|
||||
/// {@macro flutter.rendering.editable.select}
|
||||
void selectWordsInRange({ @required Offset from, Offset to, @required SelectionChangedCause cause }) {
|
||||
void selectWordsInRange({ required Offset from, Offset? to, required SelectionChangedCause cause }) {
|
||||
assert(cause != null);
|
||||
assert(from != null);
|
||||
_layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
|
||||
|
@ -1855,14 +1855,14 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
/// Move the selection to the beginning or end of a word.
|
||||
///
|
||||
/// {@macro flutter.rendering.editable.select}
|
||||
void selectWordEdge({ @required SelectionChangedCause cause }) {
|
||||
void selectWordEdge({ required SelectionChangedCause cause }) {
|
||||
assert(cause != null);
|
||||
_layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
|
||||
assert(_lastTapDownPosition != null);
|
||||
if (onSelectionChanged == null) {
|
||||
return;
|
||||
}
|
||||
final TextPosition position = _textPainter.getPositionForOffset(globalToLocal(_lastTapDownPosition - _paintOffset));
|
||||
final TextPosition position = _textPainter.getPositionForOffset(globalToLocal(_lastTapDownPosition! - _paintOffset));
|
||||
final TextRange word = _textPainter.getWordBoundary(position);
|
||||
if (position.offset - word.start <= 1) {
|
||||
_handleSelectionChange(
|
||||
|
@ -1922,7 +1922,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
_textLayoutLastMaxWidth = maxWidth;
|
||||
}
|
||||
|
||||
/*late*/ Rect _caretPrototype;
|
||||
late Rect _caretPrototype;
|
||||
|
||||
// TODO(garyq): This is no longer producing the highest-fidelity caret
|
||||
// heights for Android, especially when non-alphabetic languages
|
||||
|
@ -1996,13 +1996,13 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
// If the floating cursor is enabled, the text cursor's color is [backgroundCursorColor] while
|
||||
// the floating cursor's color is _cursorColor;
|
||||
final Paint paint = Paint()
|
||||
..color = _floatingCursorOn ? backgroundCursorColor : _cursorColor;
|
||||
..color = (_floatingCursorOn ? backgroundCursorColor : _cursorColor)!;
|
||||
final Offset caretOffset = _textPainter.getOffsetForCaret(textPosition, _caretPrototype) + effectiveOffset;
|
||||
Rect caretRect = _caretPrototype.shift(caretOffset);
|
||||
if (_cursorOffset != null)
|
||||
caretRect = caretRect.shift(_cursorOffset);
|
||||
caretRect = caretRect.shift(_cursorOffset!);
|
||||
|
||||
final double caretHeight = _textPainter.getFullHeightForCaret(textPosition, _caretPrototype);
|
||||
final double? caretHeight = _textPainter.getFullHeightForCaret(textPosition, _caretPrototype);
|
||||
if (caretHeight != null) {
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.iOS:
|
||||
|
@ -2038,20 +2038,20 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
if (cursorRadius == null) {
|
||||
canvas.drawRect(caretRect, paint);
|
||||
} else {
|
||||
final RRect caretRRect = RRect.fromRectAndRadius(caretRect, cursorRadius);
|
||||
final RRect caretRRect = RRect.fromRectAndRadius(caretRect, cursorRadius!);
|
||||
canvas.drawRRect(caretRRect, paint);
|
||||
}
|
||||
|
||||
if (caretRect != _lastCaretRect) {
|
||||
_lastCaretRect = caretRect;
|
||||
if (onCaretChanged != null)
|
||||
onCaretChanged(caretRect);
|
||||
onCaretChanged!(caretRect);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the screen position of the floating cursor and the text position
|
||||
/// closest to the cursor.
|
||||
void setFloatingCursor(FloatingCursorDragState state, Offset boundedOffset, TextPosition lastTextPosition, { double resetLerpValue }) {
|
||||
void setFloatingCursor(FloatingCursorDragState state, Offset boundedOffset, TextPosition lastTextPosition, { double? resetLerpValue }) {
|
||||
assert(state != null);
|
||||
assert(boundedOffset != null);
|
||||
assert(lastTextPosition != null);
|
||||
|
@ -2079,14 +2079,14 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
assert(_floatingCursorOn);
|
||||
|
||||
// We always want the floating cursor to render at full opacity.
|
||||
final Paint paint = Paint()..color = _cursorColor.withOpacity(0.75);
|
||||
final Paint paint = Paint()..color = _cursorColor!.withOpacity(0.75);
|
||||
|
||||
double/*!*/ sizeAdjustmentX = _kFloatingCaretSizeIncrease.dx;
|
||||
double/*!*/ sizeAdjustmentY = _kFloatingCaretSizeIncrease.dy;
|
||||
double sizeAdjustmentX = _kFloatingCaretSizeIncrease.dx;
|
||||
double sizeAdjustmentY = _kFloatingCaretSizeIncrease.dy;
|
||||
|
||||
if (_resetFloatingCursorAnimationValue != null) {
|
||||
sizeAdjustmentX = ui.lerpDouble(sizeAdjustmentX, 0, _resetFloatingCursorAnimationValue);
|
||||
sizeAdjustmentY = ui.lerpDouble(sizeAdjustmentY, 0, _resetFloatingCursorAnimationValue);
|
||||
sizeAdjustmentX = ui.lerpDouble(sizeAdjustmentX, 0, _resetFloatingCursorAnimationValue!)!;
|
||||
sizeAdjustmentY = ui.lerpDouble(sizeAdjustmentY, 0, _resetFloatingCursorAnimationValue!)!;
|
||||
}
|
||||
|
||||
final Rect floatingCaretPrototype = Rect.fromLTRB(
|
||||
|
@ -2106,12 +2106,12 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
// dragged the floating cursor offscreen. This value is used to account for the
|
||||
// difference in the rendering position and the raw offset value.
|
||||
Offset _relativeOrigin = const Offset(0, 0);
|
||||
Offset _previousOffset;
|
||||
Offset? _previousOffset;
|
||||
bool _resetOriginOnLeft = false;
|
||||
bool _resetOriginOnRight = false;
|
||||
bool _resetOriginOnTop = false;
|
||||
bool _resetOriginOnBottom = false;
|
||||
double _resetFloatingCursorAnimationValue;
|
||||
double? _resetFloatingCursorAnimationValue;
|
||||
|
||||
/// Returns the position within the text field closest to the raw cursor offset.
|
||||
Offset calculateBoundedFloatingCursorOffset(Offset rawCursorOffset) {
|
||||
|
@ -2122,7 +2122,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
final double rightBound = _textPainter.width + floatingCursorAddedMargin.right;
|
||||
|
||||
if (_previousOffset != null)
|
||||
deltaPosition = rawCursorOffset - _previousOffset;
|
||||
deltaPosition = rawCursorOffset - _previousOffset!;
|
||||
|
||||
// If the raw cursor offset has gone off an edge, we want to reset the relative
|
||||
// origin of the dragging when the user drags back into the field.
|
||||
|
@ -2166,8 +2166,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
_textLayoutLastMinWidth == constraints.minWidth,
|
||||
'Last width ($_textLayoutLastMinWidth, $_textLayoutLastMaxWidth) not the same as max width constraint (${constraints.minWidth}, ${constraints.maxWidth}).');
|
||||
assert(_selectionRects != null);
|
||||
final Paint paint = Paint()..color = _selectionColor;
|
||||
for (final ui.TextBox box in _selectionRects)
|
||||
final Paint paint = Paint()..color = _selectionColor!;
|
||||
for (final ui.TextBox box in _selectionRects!)
|
||||
canvas.drawRect(box.toRect().shift(effectiveOffset), paint);
|
||||
}
|
||||
|
||||
|
@ -2179,8 +2179,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
|
||||
final List<TextBox> boxes = _textPainter.getBoxesForSelection(
|
||||
TextSelection(
|
||||
baseOffset: _promptRectRange.start,
|
||||
extentOffset: _promptRectRange.end,
|
||||
baseOffset: _promptRectRange!.start,
|
||||
extentOffset: _promptRectRange!.end,
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -2199,16 +2199,16 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
bool showCaret = false;
|
||||
|
||||
if (selection != null && !_floatingCursorOn) {
|
||||
if (selection.isCollapsed && _showCursor.value && cursorColor != null)
|
||||
if (selection!.isCollapsed && _showCursor.value && cursorColor != null)
|
||||
showCaret = true;
|
||||
else if (!selection.isCollapsed && _selectionColor != null)
|
||||
else if (!selection!.isCollapsed && _selectionColor != null)
|
||||
showSelection = true;
|
||||
_updateSelectionExtentsVisibility(effectiveOffset);
|
||||
}
|
||||
|
||||
if (showSelection) {
|
||||
assert(selection != null);
|
||||
_selectionRects ??= _textPainter.getBoxesForSelection(selection, boxHeightStyle: _selectionHeightStyle, boxWidthStyle: _selectionWidthStyle);
|
||||
_selectionRects ??= _textPainter.getBoxesForSelection(selection!, boxHeightStyle: _selectionHeightStyle, boxWidthStyle: _selectionWidthStyle);
|
||||
_paintSelection(context.canvas, effectiveOffset);
|
||||
}
|
||||
|
||||
|
@ -2221,7 +2221,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
|
||||
if (showCaret) {
|
||||
assert(selection != null);
|
||||
_paintCaret(context.canvas, effectiveOffset, selection.extent);
|
||||
_paintCaret(context.canvas, effectiveOffset, selection!.extent);
|
||||
}
|
||||
|
||||
if (!paintCursorAboveText)
|
||||
|
@ -2237,8 +2237,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
void _paintHandleLayers(PaintingContext context, List<TextSelectionPoint> endpoints) {
|
||||
Offset startPoint = endpoints[0].point;
|
||||
startPoint = Offset(
|
||||
startPoint.dx.clamp(0.0, size.width) as double,
|
||||
startPoint.dy.clamp(0.0, size.height) as double,
|
||||
startPoint.dx.clamp(0.0, size.width),
|
||||
startPoint.dy.clamp(0.0, size.height),
|
||||
);
|
||||
context.pushLayer(
|
||||
LeaderLayer(link: startHandleLayerLink, offset: startPoint),
|
||||
|
@ -2248,8 +2248,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
if (endpoints.length == 2) {
|
||||
Offset endPoint = endpoints[1].point;
|
||||
endPoint = Offset(
|
||||
endPoint.dx.clamp(0.0, size.width) as double,
|
||||
endPoint.dy.clamp(0.0, size.height) as double,
|
||||
endPoint.dx.clamp(0.0, size.width),
|
||||
endPoint.dy.clamp(0.0, size.height),
|
||||
);
|
||||
context.pushLayer(
|
||||
LeaderLayer(link: endHandleLayerLink, offset: endPoint),
|
||||
|
@ -2265,11 +2265,11 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
context.pushClipRect(needsCompositing, offset, Offset.zero & size, _paintContents, clipBehavior: clipBehavior);
|
||||
else
|
||||
_paintContents(context, offset);
|
||||
_paintHandleLayers(context, getEndpointsForSelection(selection));
|
||||
_paintHandleLayers(context, getEndpointsForSelection(selection!));
|
||||
}
|
||||
|
||||
@override
|
||||
Rect describeApproximatePaintClip(RenderObject child) => _hasVisualOverflow ? Offset.zero & size : null;
|
||||
Rect? describeApproximatePaintClip(RenderObject child) => _hasVisualOverflow ? Offset.zero & size : null;
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
|
@ -2290,7 +2290,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
|
|||
List<DiagnosticsNode> debugDescribeChildren() {
|
||||
return <DiagnosticsNode>[
|
||||
if (text != null)
|
||||
text.toDiagnosticsNode(
|
||||
text!.toDiagnosticsNode(
|
||||
name: 'text',
|
||||
style: DiagnosticsTreeStyle.transition,
|
||||
),
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:ui' as ui show Paragraph, ParagraphBuilder, ParagraphConstraints, ParagraphStyle, TextStyle;
|
||||
|
||||
import 'box.dart';
|
||||
|
@ -59,7 +57,7 @@ class RenderErrorBox extends RenderBox {
|
|||
final String message;
|
||||
|
||||
// TODO(ianh): should be final
|
||||
/*late*/ ui.Paragraph/*?*/ _paragraph;
|
||||
ui.Paragraph? _paragraph;
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
|
@ -158,11 +156,11 @@ class RenderErrorBox extends RenderBox {
|
|||
width -= padding.left + padding.right;
|
||||
left += padding.left;
|
||||
}
|
||||
_paragraph.layout(ui.ParagraphConstraints(width: width));
|
||||
if (size.height > padding.top + _paragraph.height + padding.bottom) {
|
||||
_paragraph!.layout(ui.ParagraphConstraints(width: width));
|
||||
if (size.height > padding.top + _paragraph!.height + padding.bottom) {
|
||||
top += padding.top;
|
||||
}
|
||||
context.canvas.drawParagraph(_paragraph, offset + Offset(left, top));
|
||||
context.canvas.drawParagraph(_paragraph!, offset + Offset(left, top));
|
||||
}
|
||||
} catch (e) {
|
||||
// Intentionally left empty.
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -41,7 +39,7 @@ class FlexParentData extends ContainerBoxParentData<RenderBox> {
|
|||
/// non-zero, the amount of space the child's can occupy in the main axis is
|
||||
/// determined by dividing the free space (after placing the inflexible
|
||||
/// children) according to the flex factors of the flexible children.
|
||||
int flex;
|
||||
int? flex;
|
||||
|
||||
/// How a flexible child is inscribed into the available space.
|
||||
///
|
||||
|
@ -50,7 +48,7 @@ class FlexParentData extends ContainerBoxParentData<RenderBox> {
|
|||
/// [FlexFit.tight], the child is required to fill the available space. If the
|
||||
/// fit is [FlexFit.loose], the child can be at most as large as the available
|
||||
/// space (but is allowed to be smaller).
|
||||
FlexFit fit;
|
||||
FlexFit? fit;
|
||||
|
||||
@override
|
||||
String toString() => '${super.toString()}; flex=$flex; fit=$fit';
|
||||
|
@ -198,7 +196,7 @@ enum CrossAxisAlignment {
|
|||
baseline,
|
||||
}
|
||||
|
||||
bool/*?*/ _startIsTopLeft(Axis direction, TextDirection textDirection, VerticalDirection verticalDirection) {
|
||||
bool? _startIsTopLeft(Axis direction, TextDirection? textDirection, VerticalDirection? verticalDirection) {
|
||||
assert(direction != null);
|
||||
// If the relevant value of textDirection or verticalDirection is null, this returns null too.
|
||||
switch (direction) {
|
||||
|
@ -208,18 +206,19 @@ bool/*?*/ _startIsTopLeft(Axis direction, TextDirection textDirection, VerticalD
|
|||
return true;
|
||||
case TextDirection.rtl:
|
||||
return false;
|
||||
case null:
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case Axis.vertical:
|
||||
switch (verticalDirection) {
|
||||
case VerticalDirection.down:
|
||||
return true;
|
||||
case VerticalDirection.up:
|
||||
return false;
|
||||
case null:
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
typedef _ChildSizingFunction = double Function(RenderBox child, double extent);
|
||||
|
@ -279,14 +278,14 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
/// By default, the flex layout is horizontal and children are aligned to the
|
||||
/// start of the main axis and the center of the cross axis.
|
||||
RenderFlex({
|
||||
List<RenderBox> children,
|
||||
List<RenderBox>? children,
|
||||
Axis direction = Axis.horizontal,
|
||||
MainAxisSize mainAxisSize = MainAxisSize.max,
|
||||
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
|
||||
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
|
||||
TextDirection textDirection,
|
||||
TextDirection? textDirection,
|
||||
VerticalDirection verticalDirection = VerticalDirection.down,
|
||||
TextBaseline textBaseline,
|
||||
TextBaseline? textBaseline,
|
||||
Clip clipBehavior = Clip.none,
|
||||
}) : assert(direction != null),
|
||||
assert(mainAxisAlignment != null),
|
||||
|
@ -393,9 +392,9 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
/// If the [direction] is [Axis.vertical], and the [crossAxisAlignment] is
|
||||
/// either [CrossAxisAlignment.start] or [CrossAxisAlignment.end], then the
|
||||
/// [textDirection] must not be null.
|
||||
TextDirection get textDirection => _textDirection;
|
||||
TextDirection _textDirection;
|
||||
set textDirection(TextDirection value) {
|
||||
TextDirection? get textDirection => _textDirection;
|
||||
TextDirection? _textDirection;
|
||||
set textDirection(TextDirection? value) {
|
||||
if (_textDirection != value) {
|
||||
_textDirection = value;
|
||||
markNeedsLayout();
|
||||
|
@ -432,9 +431,9 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
/// If aligning items according to their baseline, which baseline to use.
|
||||
///
|
||||
/// Must not be null if [crossAxisAlignment] is [CrossAxisAlignment.baseline].
|
||||
TextBaseline get textBaseline => _textBaseline;
|
||||
TextBaseline _textBaseline;
|
||||
set textBaseline(TextBaseline value) {
|
||||
TextBaseline? get textBaseline => _textBaseline;
|
||||
TextBaseline? _textBaseline;
|
||||
set textBaseline(TextBaseline? value) {
|
||||
assert(_crossAxisAlignment != CrossAxisAlignment.baseline || value != null);
|
||||
if (_textBaseline != value) {
|
||||
_textBaseline = value;
|
||||
|
@ -482,10 +481,10 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
}
|
||||
|
||||
// Set during layout if overflow occurred on the main axis.
|
||||
double _overflow;
|
||||
double? _overflow;
|
||||
// Check whether any meaningful overflow is present. Values below an epsilon
|
||||
// are treated as not overflowing.
|
||||
bool get _hasOverflow => _overflow > precisionErrorTolerance;
|
||||
bool get _hasOverflow => _overflow! > precisionErrorTolerance;
|
||||
|
||||
/// {@macro flutter.widgets.Clip}
|
||||
///
|
||||
|
@ -508,9 +507,9 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
}
|
||||
|
||||
double _getIntrinsicSize({
|
||||
@required Axis sizingDirection,
|
||||
@required double extent, // the extent in the direction that isn't the sizing direction
|
||||
@required _ChildSizingFunction childSize, // a method to find the size in the sizing direction
|
||||
required Axis sizingDirection,
|
||||
required double extent, // the extent in the direction that isn't the sizing direction
|
||||
required _ChildSizingFunction childSize, // a method to find the size in the sizing direction
|
||||
}) {
|
||||
if (_direction == sizingDirection) {
|
||||
// INTRINSIC MAIN SIZE
|
||||
|
@ -519,7 +518,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
double totalFlex = 0.0;
|
||||
double inflexibleSpace = 0.0;
|
||||
double maxFlexFractionSoFar = 0.0;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
final int flex = _getFlex(child);
|
||||
totalFlex += flex;
|
||||
|
@ -544,13 +543,12 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
int totalFlex = 0;
|
||||
double inflexibleSpace = 0.0;
|
||||
double maxCrossSize = 0.0;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
final int flex = _getFlex(child);
|
||||
totalFlex += flex;
|
||||
// TODO(ianh): these should be late final
|
||||
/*late*/ double/*!*/ mainSize;
|
||||
/*late*/ double/*!*/ crossSize;
|
||||
late final double mainSize;
|
||||
late final double crossSize;
|
||||
if (flex == 0) {
|
||||
switch (_direction) {
|
||||
case Axis.horizontal:
|
||||
|
@ -625,7 +623,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
}
|
||||
|
||||
@override
|
||||
double computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
double? computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
if (_direction == Axis.horizontal)
|
||||
return defaultComputeDistanceToHighestActualBaseline(baseline);
|
||||
return defaultComputeDistanceToFirstActualBaseline(baseline);
|
||||
|
@ -648,7 +646,6 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
case Axis.vertical:
|
||||
return child.size.width;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
double _getMainSize(RenderBox child) {
|
||||
|
@ -658,7 +655,6 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
case Axis.vertical:
|
||||
return child.size.height;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -675,8 +671,8 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
|
||||
double crossSize = 0.0;
|
||||
double allocatedSize = 0.0; // Sum of the sizes of the non-flexible children.
|
||||
RenderBox child = firstChild;
|
||||
RenderBox lastFlexChild;
|
||||
RenderBox? child = firstChild;
|
||||
RenderBox? lastFlexChild;
|
||||
while (child != null) {
|
||||
final FlexParentData childParentData = child.parentData as FlexParentData;
|
||||
totalChildren++;
|
||||
|
@ -688,7 +684,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
final String dimension = _direction == Axis.horizontal ? 'width' : 'height';
|
||||
DiagnosticsNode error, message;
|
||||
final List<DiagnosticsNode> addendum = <DiagnosticsNode>[];
|
||||
if (!canFlex && (mainAxisSize == MainAxisSize.max || _getFit(child) == FlexFit.tight)) {
|
||||
if (!canFlex && (mainAxisSize == MainAxisSize.max || _getFit(child!) == FlexFit.tight)) {
|
||||
error = ErrorSummary('RenderFlex children have non-zero flex but incoming $dimension constraints are unbounded.');
|
||||
message = ErrorDescription(
|
||||
'When a $identity is in a parent that does not provide a finite $dimension constraint, for example '
|
||||
|
@ -696,16 +692,16 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
'axis. Setting a flex on a child (e.g. using Expanded) indicates that the child is to '
|
||||
'expand to fill the remaining space in the $axis direction.'
|
||||
);
|
||||
RenderBox node = this;
|
||||
RenderBox? node = this;
|
||||
switch (_direction) {
|
||||
case Axis.horizontal:
|
||||
while (!node.constraints.hasBoundedWidth && node.parent is RenderBox)
|
||||
while (!node!.constraints.hasBoundedWidth && node.parent is RenderBox)
|
||||
node = node.parent as RenderBox;
|
||||
if (!node.constraints.hasBoundedWidth)
|
||||
node = null;
|
||||
break;
|
||||
case Axis.vertical:
|
||||
while (!node.constraints.hasBoundedHeight && node.parent is RenderBox)
|
||||
while (!node!.constraints.hasBoundedHeight && node.parent is RenderBox)
|
||||
node = node.parent as RenderBox;
|
||||
if (!node.constraints.hasBoundedHeight)
|
||||
node = null;
|
||||
|
@ -746,7 +742,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
),
|
||||
]);
|
||||
}());
|
||||
totalFlex += childParentData.flex;
|
||||
totalFlex += flex;
|
||||
lastFlexChild = child;
|
||||
} else {
|
||||
BoxConstraints innerConstraints;
|
||||
|
@ -790,8 +786,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
final int flex = _getFlex(child);
|
||||
if (flex > 0) {
|
||||
final double maxChildExtent = canFlex ? (child == lastFlexChild ? (freeSpace - allocatedFlexSpace) : spacePerFlex * flex) : double.infinity;
|
||||
// TODO(ianh): this should be late final
|
||||
/*late*/ double/*!*/ minChildExtent;
|
||||
late final double minChildExtent;
|
||||
switch (_getFit(child)) {
|
||||
case FlexFit.tight:
|
||||
assert(maxChildExtent < double.infinity);
|
||||
|
@ -845,7 +840,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
throw FlutterError('To use FlexAlignItems.baseline, you must also specify which baseline to use using the "baseline" argument.');
|
||||
return true;
|
||||
}());
|
||||
final double distance = child.getDistanceToBaseline(textBaseline, onlyReal: true);
|
||||
final double? distance = child.getDistanceToBaseline(textBaseline!, onlyReal: true);
|
||||
if (distance != null) {
|
||||
maxBaselineDistance = math.max(maxBaselineDistance, distance);
|
||||
maxSizeAboveBaseline = math.max(
|
||||
|
@ -882,9 +877,8 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
final double actualSizeDelta = actualSize - allocatedSize;
|
||||
_overflow = math.max(0.0, -actualSizeDelta);
|
||||
final double remainingSpace = math.max(0.0, actualSizeDelta);
|
||||
// TODO(ianh): these should be late final
|
||||
/*late*/ double/*!*/ leadingSpace;
|
||||
/*late*/ double/*!*/ betweenSpace;
|
||||
late final double leadingSpace;
|
||||
late final double betweenSpace;
|
||||
// flipMainAxis is used to decide whether to lay out left-to-right/top-to-bottom (false), or
|
||||
// right-to-left/bottom-to-top (true). The _startIsTopLeft will return null if there's only
|
||||
// one child and the relevant direction is null, in which case we arbitrarily decide not to
|
||||
|
@ -941,7 +935,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
childCrossPosition = 0.0;
|
||||
if (_direction == Axis.horizontal) {
|
||||
assert(textBaseline != null);
|
||||
final double distance = child.getDistanceToBaseline(textBaseline, onlyReal: true);
|
||||
final double? distance = child.getDistanceToBaseline(textBaseline!, onlyReal: true);
|
||||
if (distance != null)
|
||||
childCrossPosition = maxBaselineDistance - distance;
|
||||
}
|
||||
|
@ -967,7 +961,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
|
||||
return defaultHitTestChildren(result, position: position);
|
||||
}
|
||||
|
||||
|
@ -1021,10 +1015,10 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
Rect overflowChildRect;
|
||||
switch (_direction) {
|
||||
case Axis.horizontal:
|
||||
overflowChildRect = Rect.fromLTWH(0.0, 0.0, size.width + _overflow, 0.0);
|
||||
overflowChildRect = Rect.fromLTWH(0.0, 0.0, size.width + _overflow!, 0.0);
|
||||
break;
|
||||
case Axis.vertical:
|
||||
overflowChildRect = Rect.fromLTWH(0.0, 0.0, 0.0, size.height + _overflow);
|
||||
overflowChildRect = Rect.fromLTWH(0.0, 0.0, 0.0, size.height + _overflow!);
|
||||
break;
|
||||
}
|
||||
paintOverflowIndicator(context, offset, Offset.zero & size, overflowChildRect, overflowHints: debugOverflowHints);
|
||||
|
@ -1033,12 +1027,12 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
|||
}
|
||||
|
||||
@override
|
||||
Rect describeApproximatePaintClip(RenderObject child) => _hasOverflow ? Offset.zero & size : null;
|
||||
Rect? describeApproximatePaintClip(RenderObject child) => _hasOverflow ? Offset.zero & size : null;
|
||||
|
||||
@override
|
||||
String toStringShort() {
|
||||
String header = super.toStringShort();
|
||||
if (_overflow is double && _hasOverflow)
|
||||
if (_overflow != null && _hasOverflow)
|
||||
header += ' OVERFLOWING';
|
||||
return header;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:ui' as ui show Color;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -32,7 +30,7 @@ abstract class FlowPaintingContext {
|
|||
/// The size of the [i]th child.
|
||||
///
|
||||
/// If [i] is negative or exceeds [childCount], returns null.
|
||||
Size getChildSize(int i);
|
||||
Size? getChildSize(int i);
|
||||
|
||||
/// Paint the [i]th child using the given transform.
|
||||
///
|
||||
|
@ -59,9 +57,9 @@ abstract class FlowPaintingContext {
|
|||
/// * [RenderFlow]
|
||||
abstract class FlowDelegate {
|
||||
/// The flow will repaint whenever [repaint] notifies its listeners.
|
||||
const FlowDelegate({ Listenable repaint }) : _repaint = repaint;
|
||||
const FlowDelegate({ Listenable? repaint }) : _repaint = repaint;
|
||||
|
||||
final Listenable _repaint;
|
||||
final Listenable? _repaint;
|
||||
|
||||
/// Override to control the size of the container for the children.
|
||||
///
|
||||
|
@ -145,7 +143,7 @@ abstract class FlowDelegate {
|
|||
/// matrix, use the [FlowPaintingContext.paintChild] function from an override
|
||||
/// of the [FlowDelegate.paintChildren] function.
|
||||
class FlowParentData extends ContainerBoxParentData<RenderBox> {
|
||||
Matrix4 _transform;
|
||||
Matrix4? _transform;
|
||||
}
|
||||
|
||||
/// Implements the flow layout algorithm.
|
||||
|
@ -181,8 +179,8 @@ class RenderFlow extends RenderBox
|
|||
/// For optimal performance, consider using children that return true from
|
||||
/// [isRepaintBoundary].
|
||||
RenderFlow({
|
||||
List<RenderBox> children,
|
||||
@required FlowDelegate delegate,
|
||||
List<RenderBox>? children,
|
||||
required FlowDelegate delegate,
|
||||
}) : assert(delegate != null),
|
||||
_delegate = delegate {
|
||||
addAll(children);
|
||||
|
@ -190,7 +188,7 @@ class RenderFlow extends RenderBox
|
|||
|
||||
@override
|
||||
void setupParentData(RenderBox child) {
|
||||
final ParentData childParentData = child.parentData;
|
||||
final ParentData? childParentData = child.parentData;
|
||||
if (childParentData is FlowParentData)
|
||||
childParentData._transform = null;
|
||||
else
|
||||
|
@ -285,7 +283,7 @@ class RenderFlow extends RenderBox
|
|||
size = _getSize(constraints);
|
||||
int i = 0;
|
||||
_randomAccessChildren.clear();
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
_randomAccessChildren.add(child);
|
||||
final BoxConstraints innerConstraints = _delegate.getConstraintsForChild(i, constraints);
|
||||
|
@ -304,18 +302,18 @@ class RenderFlow extends RenderBox
|
|||
final List<int> _lastPaintOrder = <int>[];
|
||||
|
||||
// Only valid during paint.
|
||||
PaintingContext _paintingContext;
|
||||
Offset _paintingOffset;
|
||||
PaintingContext? _paintingContext;
|
||||
Offset? _paintingOffset;
|
||||
|
||||
@override
|
||||
Size getChildSize(int i) {
|
||||
Size? getChildSize(int i) {
|
||||
if (i < 0 || i >= _randomAccessChildren.length)
|
||||
return null;
|
||||
return _randomAccessChildren[i].size;
|
||||
}
|
||||
|
||||
@override
|
||||
void paintChild(int i, { Matrix4 transform, double opacity = 1.0 }) {
|
||||
void paintChild(int i, { Matrix4? transform, double opacity = 1.0 }) {
|
||||
transform ??= Matrix4.identity();
|
||||
final RenderBox child = _randomAccessChildren[i];
|
||||
final FlowParentData childParentData = child.parentData as FlowParentData;
|
||||
|
@ -341,10 +339,10 @@ class RenderFlow extends RenderBox
|
|||
context.paintChild(child, offset);
|
||||
}
|
||||
if (opacity == 1.0) {
|
||||
_paintingContext.pushTransform(needsCompositing, _paintingOffset, transform, painter);
|
||||
_paintingContext!.pushTransform(needsCompositing, _paintingOffset!, transform, painter);
|
||||
} else {
|
||||
_paintingContext.pushOpacity(_paintingOffset, ui.Color.getAlphaFromOpacity(opacity), (PaintingContext context, Offset offset) {
|
||||
context.pushTransform(needsCompositing, offset, transform, painter);
|
||||
_paintingContext!.pushOpacity(_paintingOffset!, ui.Color.getAlphaFromOpacity(opacity), (PaintingContext context, Offset offset) {
|
||||
context.pushTransform(needsCompositing, offset, transform!, painter);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -371,7 +369,7 @@ class RenderFlow extends RenderBox
|
|||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
|
||||
final List<RenderBox> children = getChildrenAsList();
|
||||
for (int i = _lastPaintOrder.length - 1; i >= 0; --i) {
|
||||
final int childIndex = _lastPaintOrder[i];
|
||||
|
@ -379,14 +377,14 @@ class RenderFlow extends RenderBox
|
|||
continue;
|
||||
final RenderBox child = children[childIndex];
|
||||
final FlowParentData childParentData = child.parentData as FlowParentData;
|
||||
final Matrix4 transform = childParentData._transform;
|
||||
final Matrix4? transform = childParentData._transform;
|
||||
if (transform == null)
|
||||
continue;
|
||||
final bool absorbed = result.addWithPaintTransform(
|
||||
transform: transform,
|
||||
position: position,
|
||||
hitTest: (BoxHitTestResult result, Offset position) {
|
||||
return child.hitTest(result, position: position);
|
||||
hitTest: (BoxHitTestResult result, Offset? position) {
|
||||
return child.hitTest(result, position: position!);
|
||||
},
|
||||
);
|
||||
if (absorbed)
|
||||
|
@ -399,7 +397,7 @@ class RenderFlow extends RenderBox
|
|||
void applyPaintTransform(RenderBox child, Matrix4 transform) {
|
||||
final FlowParentData childParentData = child.parentData as FlowParentData;
|
||||
if (childParentData._transform != null)
|
||||
transform.multiply(childParentData._transform);
|
||||
transform.multiply(childParentData._transform!);
|
||||
super.applyPaintTransform(child, transform);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:ui' as ui show Image;
|
||||
|
||||
import 'box.dart';
|
||||
|
@ -27,19 +25,19 @@ class RenderImage extends RenderBox {
|
|||
/// must not be null. The [textDirection] argument must not be null if
|
||||
/// [alignment] will need resolving or if [matchTextDirection] is true.
|
||||
RenderImage({
|
||||
ui.Image image,
|
||||
ui.Image? image,
|
||||
this.debugImageLabel,
|
||||
double width,
|
||||
double height,
|
||||
double? width,
|
||||
double? height,
|
||||
double scale = 1.0,
|
||||
Color color,
|
||||
BlendMode colorBlendMode,
|
||||
BoxFit fit,
|
||||
Color? color,
|
||||
BlendMode? colorBlendMode,
|
||||
BoxFit? fit,
|
||||
AlignmentGeometry alignment = Alignment.center,
|
||||
ImageRepeat repeat = ImageRepeat.noRepeat,
|
||||
Rect centerSlice,
|
||||
Rect? centerSlice,
|
||||
bool matchTextDirection = false,
|
||||
TextDirection textDirection,
|
||||
TextDirection? textDirection,
|
||||
bool invertColors = false,
|
||||
bool isAntiAlias = false,
|
||||
FilterQuality filterQuality = FilterQuality.low,
|
||||
|
@ -67,8 +65,8 @@ class RenderImage extends RenderBox {
|
|||
_updateColorFilter();
|
||||
}
|
||||
|
||||
Alignment _resolvedAlignment;
|
||||
bool _flipHorizontally;
|
||||
Alignment? _resolvedAlignment;
|
||||
bool? _flipHorizontally;
|
||||
|
||||
void _resolve() {
|
||||
if (_resolvedAlignment != null)
|
||||
|
@ -84,9 +82,9 @@ class RenderImage extends RenderBox {
|
|||
}
|
||||
|
||||
/// The image to display.
|
||||
ui.Image get image => _image;
|
||||
ui.Image _image;
|
||||
set image(ui.Image value) {
|
||||
ui.Image? get image => _image;
|
||||
ui.Image? _image;
|
||||
set image(ui.Image? value) {
|
||||
if (value == _image)
|
||||
return;
|
||||
_image = value;
|
||||
|
@ -96,15 +94,15 @@ class RenderImage extends RenderBox {
|
|||
}
|
||||
|
||||
/// A string used to identify the source of the image.
|
||||
String debugImageLabel;
|
||||
String? debugImageLabel;
|
||||
|
||||
/// If non-null, requires the image to have this width.
|
||||
///
|
||||
/// If null, the image will pick a size that best preserves its intrinsic
|
||||
/// aspect ratio.
|
||||
double get width => _width;
|
||||
double _width;
|
||||
set width(double value) {
|
||||
double? get width => _width;
|
||||
double? _width;
|
||||
set width(double? value) {
|
||||
if (value == _width)
|
||||
return;
|
||||
_width = value;
|
||||
|
@ -115,9 +113,9 @@ class RenderImage extends RenderBox {
|
|||
///
|
||||
/// If null, the image will pick a size that best preserves its intrinsic
|
||||
/// aspect ratio.
|
||||
double get height => _height;
|
||||
double _height;
|
||||
set height(double value) {
|
||||
double? get height => _height;
|
||||
double? _height;
|
||||
set height(double? value) {
|
||||
if (value == _height)
|
||||
return;
|
||||
_height = value;
|
||||
|
@ -137,19 +135,19 @@ class RenderImage extends RenderBox {
|
|||
markNeedsLayout();
|
||||
}
|
||||
|
||||
ColorFilter _colorFilter;
|
||||
ColorFilter? _colorFilter;
|
||||
|
||||
void _updateColorFilter() {
|
||||
if (_color == null)
|
||||
_colorFilter = null;
|
||||
else
|
||||
_colorFilter = ColorFilter.mode(_color, _colorBlendMode ?? BlendMode.srcIn);
|
||||
_colorFilter = ColorFilter.mode(_color!, _colorBlendMode ?? BlendMode.srcIn);
|
||||
}
|
||||
|
||||
/// If non-null, this color is blended with each image pixel using [colorBlendMode].
|
||||
Color get color => _color;
|
||||
Color _color;
|
||||
set color(Color value) {
|
||||
Color? get color => _color;
|
||||
Color? _color;
|
||||
set color(Color? value) {
|
||||
if (value == _color)
|
||||
return;
|
||||
_color = value;
|
||||
|
@ -180,9 +178,9 @@ class RenderImage extends RenderBox {
|
|||
/// See also:
|
||||
///
|
||||
/// * [BlendMode], which includes an illustration of the effect of each blend mode.
|
||||
BlendMode get colorBlendMode => _colorBlendMode;
|
||||
BlendMode _colorBlendMode;
|
||||
set colorBlendMode(BlendMode value) {
|
||||
BlendMode? get colorBlendMode => _colorBlendMode;
|
||||
BlendMode? _colorBlendMode;
|
||||
set colorBlendMode(BlendMode? value) {
|
||||
if (value == _colorBlendMode)
|
||||
return;
|
||||
_colorBlendMode = value;
|
||||
|
@ -194,9 +192,9 @@ class RenderImage extends RenderBox {
|
|||
///
|
||||
/// The default varies based on the other fields. See the discussion at
|
||||
/// [paintImage].
|
||||
BoxFit get fit => _fit;
|
||||
BoxFit _fit;
|
||||
set fit(BoxFit value) {
|
||||
BoxFit? get fit => _fit;
|
||||
BoxFit? _fit;
|
||||
set fit(BoxFit? value) {
|
||||
if (value == _fit)
|
||||
return;
|
||||
_fit = value;
|
||||
|
@ -235,9 +233,9 @@ class RenderImage extends RenderBox {
|
|||
/// region of the image above and below the center slice will be stretched
|
||||
/// only horizontally and the region of the image to the left and right of
|
||||
/// the center slice will be stretched only vertically.
|
||||
Rect get centerSlice => _centerSlice;
|
||||
Rect _centerSlice;
|
||||
set centerSlice(Rect value) {
|
||||
Rect? get centerSlice => _centerSlice;
|
||||
Rect? _centerSlice;
|
||||
set centerSlice(Rect? value) {
|
||||
if (value == _centerSlice)
|
||||
return;
|
||||
_centerSlice = value;
|
||||
|
@ -287,9 +285,9 @@ class RenderImage extends RenderBox {
|
|||
/// This may be changed to null, but only after the [alignment] and
|
||||
/// [matchTextDirection] properties have been changed to values that do not
|
||||
/// depend on the direction.
|
||||
TextDirection get textDirection => _textDirection;
|
||||
TextDirection _textDirection;
|
||||
set textDirection(TextDirection value) {
|
||||
TextDirection? get textDirection => _textDirection;
|
||||
TextDirection? _textDirection;
|
||||
set textDirection(TextDirection? value) {
|
||||
if (_textDirection == value)
|
||||
return;
|
||||
_textDirection = value;
|
||||
|
@ -329,8 +327,8 @@ class RenderImage extends RenderBox {
|
|||
return constraints.smallest;
|
||||
|
||||
return constraints.constrainSizeAndAttemptToPreserveAspectRatio(Size(
|
||||
_image.width.toDouble() / _scale,
|
||||
_image.height.toDouble() / _scale,
|
||||
_image!.width.toDouble() / _scale,
|
||||
_image!.height.toDouble() / _scale,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -380,15 +378,15 @@ class RenderImage extends RenderBox {
|
|||
paintImage(
|
||||
canvas: context.canvas,
|
||||
rect: offset & size,
|
||||
image: _image,
|
||||
image: _image!,
|
||||
debugImageLabel: debugImageLabel,
|
||||
scale: _scale,
|
||||
colorFilter: _colorFilter,
|
||||
fit: _fit,
|
||||
alignment: _resolvedAlignment,
|
||||
alignment: _resolvedAlignment!,
|
||||
centerSlice: _centerSlice,
|
||||
repeat: _repeat,
|
||||
flipHorizontally: _flipHorizontally,
|
||||
flipHorizontally: _flipHorizontally!,
|
||||
invertColors: invertColors,
|
||||
filterQuality: _filterQuality,
|
||||
isAntiAlias: _isAntiAlias,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'box.dart';
|
||||
|
@ -32,7 +30,7 @@ class RenderListBody extends RenderBox
|
|||
///
|
||||
/// By default, children are arranged along the vertical axis.
|
||||
RenderListBody({
|
||||
List<RenderBox> children,
|
||||
List<RenderBox>? children,
|
||||
AxisDirection axisDirection = AxisDirection.down,
|
||||
}) : assert(axisDirection != null),
|
||||
_axisDirection = axisDirection {
|
||||
|
@ -123,7 +121,7 @@ class RenderListBody extends RenderBox
|
|||
]);
|
||||
}());
|
||||
double mainAxisExtent = 0.0;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
switch (axisDirection) {
|
||||
case AxisDirection.right:
|
||||
final BoxConstraints innerConstraints = BoxConstraints.tightFor(height: constraints.maxHeight);
|
||||
|
@ -201,7 +199,7 @@ class RenderListBody extends RenderBox
|
|||
|
||||
double _getIntrinsicCrossAxis(_ChildSizingFunction childSize) {
|
||||
double extent = 0.0;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
extent = math.max(extent, childSize(child));
|
||||
final ListBodyParentData childParentData = child.parentData as ListBodyParentData;
|
||||
|
@ -212,7 +210,7 @@ class RenderListBody extends RenderBox
|
|||
|
||||
double _getIntrinsicMainAxis(_ChildSizingFunction childSize) {
|
||||
double extent = 0.0;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
extent += childSize(child);
|
||||
final ListBodyParentData childParentData = child.parentData as ListBodyParentData;
|
||||
|
@ -230,7 +228,6 @@ class RenderListBody extends RenderBox
|
|||
case Axis.vertical:
|
||||
return _getIntrinsicCrossAxis((RenderBox child) => child.getMinIntrinsicWidth(height));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -242,7 +239,6 @@ class RenderListBody extends RenderBox
|
|||
case Axis.vertical:
|
||||
return _getIntrinsicCrossAxis((RenderBox child) => child.getMaxIntrinsicWidth(height));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -254,7 +250,6 @@ class RenderListBody extends RenderBox
|
|||
case Axis.vertical:
|
||||
return _getIntrinsicCrossAxis((RenderBox child) => child.getMinIntrinsicHeight(width));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -266,11 +261,10 @@ class RenderListBody extends RenderBox
|
|||
case Axis.vertical:
|
||||
return _getIntrinsicCrossAxis((RenderBox child) => child.getMaxIntrinsicHeight(width));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
double? computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
return defaultComputeDistanceToFirstActualBaseline(baseline);
|
||||
}
|
||||
|
||||
|
@ -280,7 +274,7 @@ class RenderListBody extends RenderBox
|
|||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
|
||||
return defaultHitTestChildren(result, position: position);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,9 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/animation.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:vector_math/vector_math_64.dart' show Matrix4;
|
||||
|
||||
import 'box.dart';
|
||||
|
@ -30,7 +27,7 @@ abstract class ListWheelChildManager {
|
|||
/// If null, then there's no explicit limits to the range of the children
|
||||
/// except that it has to be contiguous. If [childExistsAt] for a certain
|
||||
/// index returns false, that index is already past the limit.
|
||||
int get childCount;
|
||||
int? get childCount;
|
||||
|
||||
/// Checks whether the delegate is able to provide a child widget at the given
|
||||
/// index.
|
||||
|
@ -44,7 +41,7 @@ abstract class ListWheelChildManager {
|
|||
/// nothing.
|
||||
///
|
||||
/// It is possible to create children with negative indices.
|
||||
void createChild(int index, { @required RenderBox after });
|
||||
void createChild(int index, { required RenderBox? after });
|
||||
|
||||
/// Removes the child element corresponding with the given RenderBox.
|
||||
void removeChild(RenderBox child);
|
||||
|
@ -53,7 +50,9 @@ abstract class ListWheelChildManager {
|
|||
/// [ParentData] for use with [RenderListWheelViewport].
|
||||
class ListWheelParentData extends ContainerBoxParentData<RenderBox> {
|
||||
/// Index of this child in its parent's child list.
|
||||
int index;
|
||||
///
|
||||
/// This must be maintained by the [ListWheelChildManager].
|
||||
int? index;
|
||||
}
|
||||
|
||||
/// Render, onto a wheel, a bigger sequential set of objects inside this viewport.
|
||||
|
@ -135,19 +134,19 @@ class RenderListWheelViewport
|
|||
///
|
||||
/// All arguments must not be null. Optional arguments have reasonable defaults.
|
||||
RenderListWheelViewport({
|
||||
@required this.childManager,
|
||||
@required ViewportOffset offset,
|
||||
required this.childManager,
|
||||
required ViewportOffset offset,
|
||||
double diameterRatio = defaultDiameterRatio,
|
||||
double perspective = defaultPerspective,
|
||||
double offAxisFraction = 0,
|
||||
bool useMagnifier = false,
|
||||
double magnification = 1,
|
||||
double overAndUnderCenterOpacity = 1,
|
||||
@required double itemExtent,
|
||||
required double itemExtent,
|
||||
double squeeze = 1,
|
||||
bool renderChildrenOutsideViewport = false,
|
||||
Clip clipBehavior = Clip.none,
|
||||
List<RenderBox> children,
|
||||
List<RenderBox>? children,
|
||||
}) : assert(childManager != null),
|
||||
assert(offset != null),
|
||||
assert(diameterRatio != null),
|
||||
|
@ -208,6 +207,8 @@ class RenderListWheelViewport
|
|||
'rendered outside will be clipped anyway.';
|
||||
|
||||
/// The delegate that manages the children of this object.
|
||||
///
|
||||
/// This delegate must maintain the [ListWheelParentData.index] value.
|
||||
final ListWheelChildManager childManager;
|
||||
|
||||
/// The associated ViewportOffset object for the viewport describing the part
|
||||
|
@ -530,7 +531,7 @@ class RenderListWheelViewport
|
|||
if (childManager.childCount == null)
|
||||
return double.infinity;
|
||||
|
||||
return math.max(0.0, (childManager.childCount - 1) * _itemExtent);
|
||||
return math.max(0.0, (childManager.childCount! - 1) * _itemExtent);
|
||||
}
|
||||
|
||||
/// Scroll extent distance in the untransformed plane between the center
|
||||
|
@ -567,7 +568,7 @@ class RenderListWheelViewport
|
|||
|
||||
double _getIntrinsicCrossAxis(_ChildSizingFunction childSize) {
|
||||
double extent = 0.0;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
extent = math.max(extent, childSize(child));
|
||||
child = childAfter(child);
|
||||
|
@ -593,14 +594,14 @@ class RenderListWheelViewport
|
|||
double computeMinIntrinsicHeight(double width) {
|
||||
if (childManager.childCount == null)
|
||||
return 0.0;
|
||||
return childManager.childCount * _itemExtent;
|
||||
return childManager.childCount! * _itemExtent;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
if (childManager.childCount == null)
|
||||
return 0.0;
|
||||
return childManager.childCount * _itemExtent;
|
||||
return childManager.childCount! * _itemExtent;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -611,12 +612,14 @@ class RenderListWheelViewport
|
|||
size = constraints.biggest;
|
||||
}
|
||||
|
||||
/// Gets the index of a child by looking at its parentData.
|
||||
/// Gets the index of a child by looking at its [parentData].
|
||||
///
|
||||
/// This relies on the [childManager] maintaining [ListWheelParentData.index].
|
||||
int indexOf(RenderBox child) {
|
||||
assert(child != null);
|
||||
final ListWheelParentData childParentData = child.parentData as ListWheelParentData;
|
||||
assert(childParentData.index != null);
|
||||
return childParentData.index;
|
||||
return childParentData.index!;
|
||||
}
|
||||
|
||||
/// Returns the index of the child at the given offset.
|
||||
|
@ -625,7 +628,7 @@ class RenderListWheelViewport
|
|||
/// Returns the scroll offset of the child with the given index.
|
||||
double indexToScrollOffset(int index) => index * itemExtent;
|
||||
|
||||
void _createChild(int index, { RenderBox after }) {
|
||||
void _createChild(int index, { RenderBox? after }) {
|
||||
invokeLayoutCallback<BoxConstraints>((BoxConstraints constraints) {
|
||||
assert(constraints == this.constraints);
|
||||
childManager.createChild(index, after: after);
|
||||
|
@ -697,7 +700,7 @@ class RenderListWheelViewport
|
|||
// return.
|
||||
if (targetFirstIndex > targetLastIndex) {
|
||||
while (firstChild != null)
|
||||
_destroyChild(firstChild);
|
||||
_destroyChild(firstChild!);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -711,34 +714,34 @@ class RenderListWheelViewport
|
|||
|
||||
// Case when there is no intersection.
|
||||
if (childCount > 0 &&
|
||||
(indexOf(firstChild) > targetLastIndex || indexOf(lastChild) < targetFirstIndex)) {
|
||||
(indexOf(firstChild!) > targetLastIndex || indexOf(lastChild!) < targetFirstIndex)) {
|
||||
while (firstChild != null)
|
||||
_destroyChild(firstChild);
|
||||
_destroyChild(firstChild!);
|
||||
}
|
||||
|
||||
// If there is no child at this stage, we add the first one that is in
|
||||
// target range.
|
||||
if (childCount == 0) {
|
||||
_createChild(targetFirstIndex);
|
||||
_layoutChild(firstChild, childConstraints, targetFirstIndex);
|
||||
_layoutChild(firstChild!, childConstraints, targetFirstIndex);
|
||||
}
|
||||
|
||||
int currentFirstIndex = indexOf(firstChild);
|
||||
int currentLastIndex = indexOf(lastChild);
|
||||
int currentFirstIndex = indexOf(firstChild!);
|
||||
int currentLastIndex = indexOf(lastChild!);
|
||||
|
||||
// Remove all unnecessary children by shortening the current child list, in
|
||||
// both directions.
|
||||
while (currentFirstIndex < targetFirstIndex) {
|
||||
_destroyChild(firstChild);
|
||||
_destroyChild(firstChild!);
|
||||
currentFirstIndex++;
|
||||
}
|
||||
while (currentLastIndex > targetLastIndex) {
|
||||
_destroyChild(lastChild);
|
||||
_destroyChild(lastChild!);
|
||||
currentLastIndex--;
|
||||
}
|
||||
|
||||
// Relayout all active children.
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
child.layout(childConstraints, parentUsesSize: true);
|
||||
child = childAfter(child);
|
||||
|
@ -747,11 +750,11 @@ class RenderListWheelViewport
|
|||
// Spawning new children that are actually visible but not in child list yet.
|
||||
while (currentFirstIndex > targetFirstIndex) {
|
||||
_createChild(currentFirstIndex - 1);
|
||||
_layoutChild(firstChild, childConstraints, --currentFirstIndex);
|
||||
_layoutChild(firstChild!, childConstraints, --currentFirstIndex);
|
||||
}
|
||||
while (currentLastIndex < targetLastIndex) {
|
||||
_createChild(currentLastIndex + 1, after: lastChild);
|
||||
_layoutChild(lastChild, childConstraints, ++currentLastIndex);
|
||||
_layoutChild(lastChild!, childConstraints, ++currentLastIndex);
|
||||
}
|
||||
|
||||
offset.applyViewportDimension(_viewportExtent);
|
||||
|
@ -796,13 +799,11 @@ class RenderListWheelViewport
|
|||
|
||||
/// Paints all children visible in the current viewport.
|
||||
void _paintVisibleChildren(PaintingContext context, Offset offset) {
|
||||
RenderBox childToPaint = firstChild;
|
||||
ListWheelParentData childParentData = childToPaint?.parentData as ListWheelParentData;
|
||||
|
||||
while (childParentData != null) {
|
||||
RenderBox? childToPaint = firstChild;
|
||||
while (childToPaint != null) {
|
||||
final ListWheelParentData childParentData = childToPaint.parentData! as ListWheelParentData;
|
||||
_paintTransformedChild(childToPaint, context, offset, childParentData.offset);
|
||||
childToPaint = childAfter(childToPaint);
|
||||
childParentData = childToPaint?.parentData as ListWheelParentData;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -988,23 +989,23 @@ class RenderListWheelViewport
|
|||
/// painting coordinates** system.
|
||||
@override
|
||||
void applyPaintTransform(RenderBox child, Matrix4 transform) {
|
||||
final ListWheelParentData parentData = child?.parentData as ListWheelParentData;
|
||||
final ListWheelParentData parentData = child.parentData as ListWheelParentData;
|
||||
transform.translate(0.0, _getUntransformedPaintingCoordinateY(parentData.offset.dy));
|
||||
}
|
||||
|
||||
@override
|
||||
Rect describeApproximatePaintClip(RenderObject child) {
|
||||
if (child != null && _shouldClipAtCurrentOffset()) {
|
||||
Rect? describeApproximatePaintClip(RenderObject child) {
|
||||
if (_shouldClipAtCurrentOffset()) {
|
||||
return Offset.zero & size;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, { Offset position }) => false;
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) => false;
|
||||
|
||||
@override
|
||||
RevealedOffset getOffsetToReveal(RenderObject target, double alignment, { Rect rect }) {
|
||||
RevealedOffset getOffsetToReveal(RenderObject target, double alignment, { Rect? rect }) {
|
||||
// `target` is only fully revealed when in the selected/center position. Therefore,
|
||||
// this method always returns the offset that shows `target` in the center position,
|
||||
// which is the same offset for all `alignment` values.
|
||||
|
@ -1028,8 +1029,8 @@ class RenderListWheelViewport
|
|||
|
||||
@override
|
||||
void showOnScreen({
|
||||
RenderObject descendant,
|
||||
Rect rect,
|
||||
RenderObject? descendant,
|
||||
Rect? rect,
|
||||
Duration duration = Duration.zero,
|
||||
Curve curve = Curves.ease,
|
||||
}) {
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -27,8 +25,8 @@ mixin MouseTrackerCursorMixin on BaseMouseTracker {
|
|||
/// Only valid when asserts are enabled. In release builds, always returns
|
||||
/// null.
|
||||
@visibleForTesting
|
||||
MouseCursor debugDeviceActiveCursor(int device) {
|
||||
MouseCursor result;
|
||||
MouseCursor? debugDeviceActiveCursor(int device) {
|
||||
MouseCursor? result;
|
||||
assert(() {
|
||||
result = _lastSession[device]?.cursor;
|
||||
return true;
|
||||
|
@ -66,7 +64,7 @@ mixin MouseTrackerCursorMixin on BaseMouseTracker {
|
|||
return;
|
||||
}
|
||||
|
||||
final MouseCursorSession lastSession = _lastSession[device];
|
||||
final MouseCursorSession? lastSession = _lastSession[device];
|
||||
final MouseCursor nextCursor = _findFirstCursor(details.nextAnnotations.keys);
|
||||
if (lastSession?.cursor == nextCursor)
|
||||
return;
|
||||
|
@ -273,7 +271,7 @@ class _DeferringMouseCursor extends MouseCursor {
|
|||
String get debugDescription => 'defer';
|
||||
|
||||
/// Returns the first cursor that is not a [MouseCursor.defer].
|
||||
static MouseCursor firstNonDeferred(Iterable<MouseCursor> cursors) {
|
||||
static MouseCursor? firstNonDeferred(Iterable<MouseCursor> cursors) {
|
||||
for (final MouseCursor cursor in cursors) {
|
||||
assert(cursor != null);
|
||||
if (cursor != MouseCursor.defer)
|
||||
|
@ -370,7 +368,7 @@ class SystemMouseCursor extends MouseCursor {
|
|||
// Application code shouldn't directly instantiate system mouse cursors, since
|
||||
// the supported system cursors are enumerated in [SystemMouseCursors].
|
||||
const SystemMouseCursor._({
|
||||
@required this.kind,
|
||||
required this.kind,
|
||||
}) : assert(kind != null);
|
||||
|
||||
/// A string that identifies the kind of the cursor.
|
||||
|
@ -386,7 +384,7 @@ class SystemMouseCursor extends MouseCursor {
|
|||
_SystemMouseCursorSession createSession(int device) => _SystemMouseCursorSession(this, device);
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType)
|
||||
return false;
|
||||
return other is SystemMouseCursor
|
||||
|
@ -419,7 +417,7 @@ class SystemMouseCursor extends MouseCursor {
|
|||
class SystemMouseCursors {
|
||||
// This class only contains static members, and should not be instantiated or
|
||||
// extended.
|
||||
factory SystemMouseCursors._() => null;
|
||||
factory SystemMouseCursors._() => throw Error();
|
||||
|
||||
// The mapping in this class must be kept in sync with the following files in
|
||||
// the engine:
|
||||
|
@ -438,7 +436,7 @@ class SystemMouseCursors {
|
|||
static const SystemMouseCursor none = SystemMouseCursor._(kind: 'none');
|
||||
|
||||
|
||||
//// STATUS ////
|
||||
// STATUS
|
||||
|
||||
/// The platform-dependent basic cursor.
|
||||
///
|
||||
|
@ -550,7 +548,7 @@ class SystemMouseCursors {
|
|||
static const SystemMouseCursor help = SystemMouseCursor._(kind: 'help');
|
||||
|
||||
|
||||
//// SELECTION ////
|
||||
// SELECTION
|
||||
|
||||
/// A cursor indicating selectable text.
|
||||
///
|
||||
|
@ -604,7 +602,7 @@ class SystemMouseCursors {
|
|||
static const SystemMouseCursor precise = SystemMouseCursor._(kind: 'precise');
|
||||
|
||||
|
||||
//// DRAG-AND-DROP ////
|
||||
// DRAG-AND-DROP
|
||||
|
||||
/// A cursor indicating moving something.
|
||||
///
|
||||
|
@ -696,7 +694,7 @@ class SystemMouseCursors {
|
|||
static const SystemMouseCursor disappearing = SystemMouseCursor._(kind: 'disappearing');
|
||||
|
||||
|
||||
//// RESIZING AND SCROLLING ////
|
||||
// RESIZING AND SCROLLING
|
||||
|
||||
/// A cursor indicating scrolling in any direction.
|
||||
///
|
||||
|
@ -897,7 +895,7 @@ class SystemMouseCursors {
|
|||
static const SystemMouseCursor resizeRow = SystemMouseCursor._(kind: 'resizeRow');
|
||||
|
||||
|
||||
//// OTHER OPERATIONS ////
|
||||
// OTHER OPERATIONS
|
||||
|
||||
/// A cursor indicating zooming in.
|
||||
///
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:collection' show LinkedHashMap;
|
||||
import 'dart:ui';
|
||||
|
||||
|
@ -72,7 +70,7 @@ class MouseTrackerAnnotation with Diagnosticable {
|
|||
///
|
||||
/// * [onExit], which is triggered when a mouse pointer exits the region.
|
||||
/// * [MouseRegion.onEnter], which uses this callback.
|
||||
final PointerEnterEventListener onEnter;
|
||||
final PointerEnterEventListener? onEnter;
|
||||
|
||||
/// Triggered when a mouse pointer has moved onto or within the region without
|
||||
/// buttons pressed.
|
||||
|
@ -82,7 +80,7 @@ class MouseTrackerAnnotation with Diagnosticable {
|
|||
/// See also:
|
||||
///
|
||||
/// * [MouseRegion.onHover], which uses this callback.
|
||||
final PointerHoverEventListener onHover;
|
||||
final PointerHoverEventListener? onHover;
|
||||
|
||||
/// Triggered when a mouse pointer, with or without buttons pressed, has
|
||||
/// exited the region.
|
||||
|
@ -97,7 +95,7 @@ class MouseTrackerAnnotation with Diagnosticable {
|
|||
/// * [onEnter], which is triggered when a mouse pointer enters the region.
|
||||
/// * [MouseRegion.onExit], which uses this callback, but is not triggered in
|
||||
/// certain cases and does not always match its earlier [MouseRegion.onEnter].
|
||||
final PointerExitEventListener onExit;
|
||||
final PointerExitEventListener? onExit;
|
||||
|
||||
/// The mouse cursor for mouse pointers that are hovering over the region.
|
||||
///
|
||||
|
@ -116,9 +114,9 @@ class MouseTrackerAnnotation with Diagnosticable {
|
|||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(FlagsSummary<Function>(
|
||||
properties.add(FlagsSummary<Function?>(
|
||||
'callbacks',
|
||||
<String, Function> {
|
||||
<String, Function?> {
|
||||
'enter': onEnter,
|
||||
'exit': onExit,
|
||||
},
|
||||
|
@ -137,7 +135,7 @@ typedef MouseDetectorAnnotationFinder = HitTestResult Function(Offset offset);
|
|||
// Various states of a connected mouse device used by [BaseMouseTracker].
|
||||
class _MouseState {
|
||||
_MouseState({
|
||||
@required PointerEvent initialEvent,
|
||||
required PointerEvent initialEvent,
|
||||
}) : assert(initialEvent != null),
|
||||
_latestEvent = initialEvent;
|
||||
|
||||
|
@ -170,10 +168,7 @@ class _MouseState {
|
|||
|
||||
@override
|
||||
String toString() {
|
||||
String describeEvent(PointerEvent event) {
|
||||
return event == null ? 'null' : describeIdentity(event);
|
||||
}
|
||||
final String describeLatestEvent = 'latestEvent: ${describeEvent(latestEvent)}';
|
||||
final String describeLatestEvent = 'latestEvent: ${describeIdentity(latestEvent)}';
|
||||
final String describeAnnotations = 'annotations: [list of ${annotations.length}]';
|
||||
return '${describeIdentity(this)}($describeLatestEvent, $describeAnnotations)';
|
||||
}
|
||||
|
@ -191,9 +186,9 @@ class MouseTrackerUpdateDetails with Diagnosticable {
|
|||
///
|
||||
/// All parameters are required.
|
||||
const MouseTrackerUpdateDetails.byNewFrame({
|
||||
@required this.lastAnnotations,
|
||||
@required this.nextAnnotations,
|
||||
@required this.previousEvent,
|
||||
required this.lastAnnotations,
|
||||
required this.nextAnnotations,
|
||||
required this.previousEvent,
|
||||
}) : assert(previousEvent != null),
|
||||
assert(lastAnnotations != null),
|
||||
assert(nextAnnotations != null),
|
||||
|
@ -204,10 +199,10 @@ class MouseTrackerUpdateDetails with Diagnosticable {
|
|||
/// The [lastAnnotations], [nextAnnotations], and [triggeringEvent] are
|
||||
/// required.
|
||||
const MouseTrackerUpdateDetails.byPointerEvent({
|
||||
@required this.lastAnnotations,
|
||||
@required this.nextAnnotations,
|
||||
required this.lastAnnotations,
|
||||
required this.nextAnnotations,
|
||||
this.previousEvent,
|
||||
@required this.triggeringEvent,
|
||||
required PointerEvent this.triggeringEvent,
|
||||
}) : assert(triggeringEvent != null),
|
||||
assert(lastAnnotations != null),
|
||||
assert(nextAnnotations != null);
|
||||
|
@ -230,16 +225,16 @@ class MouseTrackerUpdateDetails with Diagnosticable {
|
|||
/// If the update is triggered by a pointer event, the [previousEvent] is not
|
||||
/// null except for cases where the event is the first event observed by the
|
||||
/// pointer (which is not necessarily a [PointerAddedEvent]).
|
||||
final PointerEvent previousEvent;
|
||||
final PointerEvent? previousEvent;
|
||||
|
||||
/// The event that triggered this update.
|
||||
///
|
||||
/// It is non-null if and only if the update is triggered by a pointer event.
|
||||
final PointerEvent triggeringEvent;
|
||||
final PointerEvent? triggeringEvent;
|
||||
|
||||
/// The pointing device of this update.
|
||||
int get device {
|
||||
final int result = (previousEvent ?? triggeringEvent).device;
|
||||
final int result = (previousEvent ?? triggeringEvent)!.device;
|
||||
assert(result != null);
|
||||
return result;
|
||||
}
|
||||
|
@ -248,7 +243,7 @@ class MouseTrackerUpdateDetails with Diagnosticable {
|
|||
///
|
||||
/// The [latestEvent] is never null.
|
||||
PointerEvent get latestEvent {
|
||||
final PointerEvent result = triggeringEvent ?? previousEvent;
|
||||
final PointerEvent result = triggeringEvent ?? previousEvent!;
|
||||
assert(result != null);
|
||||
return result;
|
||||
}
|
||||
|
@ -327,7 +322,7 @@ abstract class BaseMouseTracker extends ChangeNotifier {
|
|||
}
|
||||
|
||||
// Whether an observed event might update a device.
|
||||
static bool _shouldMarkStateDirty(_MouseState state, PointerEvent event) {
|
||||
static bool _shouldMarkStateDirty(_MouseState? state, PointerEvent event) {
|
||||
if (state == null)
|
||||
return true;
|
||||
assert(event != null);
|
||||
|
@ -351,7 +346,7 @@ abstract class BaseMouseTracker extends ChangeNotifier {
|
|||
as LinkedHashMap<MouseTrackerAnnotation, Matrix4>;
|
||||
for (final HitTestEntry entry in result.path) {
|
||||
if (entry.target is MouseTrackerAnnotation) {
|
||||
annotations[entry.target as MouseTrackerAnnotation] = entry.transform;
|
||||
annotations[entry.target as MouseTrackerAnnotation] = entry.transform!;
|
||||
}
|
||||
}
|
||||
return annotations;
|
||||
|
@ -416,7 +411,7 @@ abstract class BaseMouseTracker extends ChangeNotifier {
|
|||
if (event is PointerSignalEvent)
|
||||
return;
|
||||
final int device = event.device;
|
||||
final _MouseState existingState = _mouseStates[device];
|
||||
final _MouseState? existingState = _mouseStates[device];
|
||||
if (!_shouldMarkStateDirty(existingState, event))
|
||||
return;
|
||||
|
||||
|
@ -433,7 +428,7 @@ abstract class BaseMouseTracker extends ChangeNotifier {
|
|||
if (event is PointerRemovedEvent)
|
||||
_mouseStates.remove(event.device);
|
||||
}
|
||||
final _MouseState targetState = _mouseStates[device] ?? existingState;
|
||||
final _MouseState targetState = _mouseStates[device] ?? existingState!;
|
||||
|
||||
final PointerEvent lastEvent = targetState.replaceLatestEvent(event);
|
||||
final LinkedHashMap<MouseTrackerAnnotation, Matrix4> nextAnnotations = event is PointerRemovedEvent ?
|
||||
|
@ -487,8 +482,8 @@ abstract class BaseMouseTracker extends ChangeNotifier {
|
|||
mixin _MouseTrackerEventMixin on BaseMouseTracker {
|
||||
// Handles device update and dispatches mouse event callbacks.
|
||||
static void _handleDeviceUpdateMouseEvents(MouseTrackerUpdateDetails details) {
|
||||
final PointerEvent previousEvent = details.previousEvent;
|
||||
final PointerEvent triggeringEvent = details.triggeringEvent;
|
||||
final PointerEvent? previousEvent = details.previousEvent;
|
||||
final PointerEvent? triggeringEvent = details.triggeringEvent;
|
||||
final PointerEvent latestEvent = details.latestEvent;
|
||||
|
||||
final LinkedHashMap<MouseTrackerAnnotation, Matrix4> lastAnnotations = details.lastAnnotations;
|
||||
|
@ -506,7 +501,7 @@ mixin _MouseTrackerEventMixin on BaseMouseTracker {
|
|||
lastAnnotations.forEach((MouseTrackerAnnotation annotation, Matrix4 transform) {
|
||||
if (!nextAnnotations.containsKey(annotation))
|
||||
if (annotation.onExit != null)
|
||||
annotation.onExit(baseExitEvent.transformed(lastAnnotations[annotation]));
|
||||
annotation.onExit!(baseExitEvent.transformed(lastAnnotations[annotation]));
|
||||
});
|
||||
|
||||
// Send enter events to annotations that are not in last but in next, in
|
||||
|
@ -517,14 +512,14 @@ mixin _MouseTrackerEventMixin on BaseMouseTracker {
|
|||
final PointerEnterEvent baseEnterEvent = PointerEnterEvent.fromMouseEvent(latestEvent);
|
||||
for (final MouseTrackerAnnotation annotation in enteringAnnotations.reversed) {
|
||||
if (annotation.onEnter != null)
|
||||
annotation.onEnter(baseEnterEvent.transformed(nextAnnotations[annotation]));
|
||||
annotation.onEnter!(baseEnterEvent.transformed(nextAnnotations[annotation]));
|
||||
}
|
||||
|
||||
// Send hover events to annotations that are in next, in reverse visual
|
||||
// order. The reverse visual order is chosen only because of the simplicity
|
||||
// by keeping the hover events aligned with enter events.
|
||||
if (triggeringEvent is PointerHoverEvent) {
|
||||
final Offset hoverPositionBeforeUpdate = previousEvent is PointerHoverEvent ? previousEvent.position : null;
|
||||
final Offset? hoverPositionBeforeUpdate = previousEvent is PointerHoverEvent ? previousEvent.position : null;
|
||||
final bool pointerHasMoved = hoverPositionBeforeUpdate == null || hoverPositionBeforeUpdate != triggeringEvent.position;
|
||||
// If the hover event follows a non-hover event, or has moved since the
|
||||
// last hover, then trigger the hover callback on all annotations.
|
||||
|
@ -533,7 +528,7 @@ mixin _MouseTrackerEventMixin on BaseMouseTracker {
|
|||
final Iterable<MouseTrackerAnnotation> hoveringAnnotations = pointerHasMoved ? nextAnnotations.keys.toList().reversed : enteringAnnotations;
|
||||
for (final MouseTrackerAnnotation annotation in hoveringAnnotations) {
|
||||
if (annotation.onHover != null) {
|
||||
annotation.onHover(triggeringEvent.transformed(nextAnnotations[annotation]));
|
||||
annotation.onHover!(triggeringEvent.transformed(nextAnnotations[annotation]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:collection';
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui' as ui show Gradient, Shader, TextBox, PlaceholderAlignment, TextHeightBehavior;
|
||||
|
@ -43,7 +41,7 @@ const String _kEllipsis = '\u2026';
|
|||
/// Parent data for use with [RenderParagraph].
|
||||
class TextParentData extends ContainerBoxParentData<RenderBox> {
|
||||
/// The scaling of the text.
|
||||
double scale;
|
||||
double? scale;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
|
@ -70,16 +68,16 @@ class RenderParagraph extends RenderBox
|
|||
/// it is not null, it must be greater than zero.
|
||||
RenderParagraph(InlineSpan text, {
|
||||
TextAlign textAlign = TextAlign.start,
|
||||
@required TextDirection textDirection,
|
||||
required TextDirection textDirection,
|
||||
bool softWrap = true,
|
||||
TextOverflow overflow = TextOverflow.clip,
|
||||
double textScaleFactor = 1.0,
|
||||
int maxLines,
|
||||
Locale locale,
|
||||
StrutStyle strutStyle,
|
||||
int? maxLines,
|
||||
Locale? locale,
|
||||
StrutStyle? strutStyle,
|
||||
TextWidthBasis textWidthBasis = TextWidthBasis.parent,
|
||||
ui.TextHeightBehavior textHeightBehavior,
|
||||
List<RenderBox> children,
|
||||
ui.TextHeightBehavior? textHeightBehavior,
|
||||
List<RenderBox>? children,
|
||||
}) : assert(text != null),
|
||||
assert(text.debugAssertIsValid()),
|
||||
assert(textAlign != null),
|
||||
|
@ -116,10 +114,10 @@ class RenderParagraph extends RenderBox
|
|||
final TextPainter _textPainter;
|
||||
|
||||
/// The text to display.
|
||||
InlineSpan get text => _textPainter.text;
|
||||
InlineSpan get text => _textPainter.text!;
|
||||
set text(InlineSpan value) {
|
||||
assert(value != null);
|
||||
switch (_textPainter.text.compareTo(value)) {
|
||||
switch (_textPainter.text!.compareTo(value)) {
|
||||
case RenderComparison.identical:
|
||||
case RenderComparison.metadata:
|
||||
return;
|
||||
|
@ -138,13 +136,12 @@ class RenderParagraph extends RenderBox
|
|||
}
|
||||
}
|
||||
|
||||
List<PlaceholderSpan> _placeholderSpans;
|
||||
late List<PlaceholderSpan> _placeholderSpans;
|
||||
void _extractPlaceholderSpans(InlineSpan span) {
|
||||
_placeholderSpans = <PlaceholderSpan>[];
|
||||
span.visitChildren((InlineSpan span) {
|
||||
if (span is PlaceholderSpan) {
|
||||
final PlaceholderSpan placeholderSpan = span;
|
||||
_placeholderSpans.add(placeholderSpan);
|
||||
_placeholderSpans.add(span);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
@ -173,7 +170,7 @@ class RenderParagraph extends RenderBox
|
|||
/// its left.
|
||||
///
|
||||
/// This must not be null.
|
||||
TextDirection get textDirection => _textPainter.textDirection;
|
||||
TextDirection get textDirection => _textPainter.textDirection!;
|
||||
set textDirection(TextDirection value) {
|
||||
assert(value != null);
|
||||
if (_textPainter.textDirection == value)
|
||||
|
@ -228,10 +225,10 @@ class RenderParagraph extends RenderBox
|
|||
/// An optional maximum number of lines for the text to span, wrapping if
|
||||
/// necessary. If the text exceeds the given number of lines, it will be
|
||||
/// truncated according to [overflow] and [softWrap].
|
||||
int get maxLines => _textPainter.maxLines;
|
||||
int? get maxLines => _textPainter.maxLines;
|
||||
/// The value may be null. If it is not null, then it must be greater than
|
||||
/// zero.
|
||||
set maxLines(int value) {
|
||||
set maxLines(int? value) {
|
||||
assert(value == null || value > 0);
|
||||
if (_textPainter.maxLines == value)
|
||||
return;
|
||||
|
@ -248,9 +245,9 @@ class RenderParagraph extends RenderBox
|
|||
/// on the locale. For example the '骨' character is rendered differently in
|
||||
/// the Chinese and Japanese locales. In these cases the [locale] may be used
|
||||
/// to select a locale-specific font.
|
||||
Locale get locale => _textPainter.locale;
|
||||
Locale? get locale => _textPainter.locale;
|
||||
/// The value may be null.
|
||||
set locale(Locale value) {
|
||||
set locale(Locale? value) {
|
||||
if (_textPainter.locale == value)
|
||||
return;
|
||||
_textPainter.locale = value;
|
||||
|
@ -259,9 +256,9 @@ class RenderParagraph extends RenderBox
|
|||
}
|
||||
|
||||
/// {@macro flutter.painting.textPainter.strutStyle}
|
||||
StrutStyle get strutStyle => _textPainter.strutStyle;
|
||||
StrutStyle? get strutStyle => _textPainter.strutStyle;
|
||||
/// The value may be null.
|
||||
set strutStyle(StrutStyle value) {
|
||||
set strutStyle(StrutStyle? value) {
|
||||
if (_textPainter.strutStyle == value)
|
||||
return;
|
||||
_textPainter.strutStyle = value;
|
||||
|
@ -281,8 +278,8 @@ class RenderParagraph extends RenderBox
|
|||
}
|
||||
|
||||
/// {@macro flutter.dart:ui.textHeightBehavior}
|
||||
ui.TextHeightBehavior get textHeightBehavior => _textPainter.textHeightBehavior;
|
||||
set textHeightBehavior(ui.TextHeightBehavior value) {
|
||||
ui.TextHeightBehavior? get textHeightBehavior => _textPainter.textHeightBehavior;
|
||||
set textHeightBehavior(ui.TextHeightBehavior? value) {
|
||||
if (_textPainter.textHeightBehavior == value)
|
||||
return;
|
||||
_textPainter.textHeightBehavior = value;
|
||||
|
@ -369,8 +366,8 @@ class RenderParagraph extends RenderBox
|
|||
}
|
||||
|
||||
void _computeChildrenWidthWithMaxIntrinsics(double height) {
|
||||
RenderBox child = firstChild;
|
||||
final List<PlaceholderDimensions> placeholderDimensions = List<PlaceholderDimensions>(childCount);
|
||||
RenderBox? child = firstChild;
|
||||
final List<PlaceholderDimensions> placeholderDimensions = List<PlaceholderDimensions>.filled(childCount, PlaceholderDimensions.empty, growable: false);
|
||||
int childIndex = 0;
|
||||
// Takes textScaleFactor into account because the content of the placeholder
|
||||
// span will be scale up when it paints.
|
||||
|
@ -386,12 +383,12 @@ class RenderParagraph extends RenderBox
|
|||
child = childAfter(child);
|
||||
childIndex += 1;
|
||||
}
|
||||
_textPainter.setPlaceholderDimensions(placeholderDimensions);
|
||||
_textPainter.setPlaceholderDimensions(placeholderDimensions.cast<PlaceholderDimensions>());
|
||||
}
|
||||
|
||||
void _computeChildrenWidthWithMinIntrinsics(double height) {
|
||||
RenderBox child = firstChild;
|
||||
final List<PlaceholderDimensions> placeholderDimensions = List<PlaceholderDimensions>(childCount);
|
||||
RenderBox? child = firstChild;
|
||||
final List<PlaceholderDimensions> placeholderDimensions = List<PlaceholderDimensions>.filled(childCount, PlaceholderDimensions.empty, growable: false);
|
||||
int childIndex = 0;
|
||||
// Takes textScaleFactor into account because the content of the placeholder
|
||||
// span will be scale up when it paints.
|
||||
|
@ -407,12 +404,12 @@ class RenderParagraph extends RenderBox
|
|||
child = childAfter(child);
|
||||
childIndex += 1;
|
||||
}
|
||||
_textPainter.setPlaceholderDimensions(placeholderDimensions);
|
||||
_textPainter.setPlaceholderDimensions(placeholderDimensions.cast<PlaceholderDimensions>());
|
||||
}
|
||||
|
||||
void _computeChildrenHeightWithMinIntrinsics(double width) {
|
||||
RenderBox child = firstChild;
|
||||
final List<PlaceholderDimensions> placeholderDimensions = List<PlaceholderDimensions>(childCount);
|
||||
RenderBox? child = firstChild;
|
||||
final List<PlaceholderDimensions> placeholderDimensions = List<PlaceholderDimensions>.filled(childCount, PlaceholderDimensions.empty, growable: false);
|
||||
int childIndex = 0;
|
||||
// Takes textScaleFactor into account because the content of the placeholder
|
||||
// span will be scale up when it paints.
|
||||
|
@ -428,15 +425,15 @@ class RenderParagraph extends RenderBox
|
|||
child = childAfter(child);
|
||||
childIndex += 1;
|
||||
}
|
||||
_textPainter.setPlaceholderDimensions(placeholderDimensions);
|
||||
_textPainter.setPlaceholderDimensions(placeholderDimensions.cast<PlaceholderDimensions>());
|
||||
}
|
||||
|
||||
@override
|
||||
bool hitTestSelf(Offset position) => true;
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
|
||||
RenderBox child = firstChild;
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
final TextParentData textParentData = child.parentData as TextParentData;
|
||||
final Matrix4 transform = Matrix4.translationValues(
|
||||
|
@ -451,13 +448,13 @@ class RenderParagraph extends RenderBox
|
|||
final bool isHit = result.addWithPaintTransform(
|
||||
transform: transform,
|
||||
position: position,
|
||||
hitTest: (BoxHitTestResult result, Offset transformed) {
|
||||
hitTest: (BoxHitTestResult result, Offset? transformed) {
|
||||
assert(() {
|
||||
final Offset manualPosition = (position - textParentData.offset) / textParentData.scale;
|
||||
return (transformed.dx - manualPosition.dx).abs() < precisionErrorTolerance
|
||||
final Offset manualPosition = (position - textParentData.offset) / textParentData.scale!;
|
||||
return (transformed!.dx - manualPosition.dx).abs() < precisionErrorTolerance
|
||||
&& (transformed.dy - manualPosition.dy).abs() < precisionErrorTolerance;
|
||||
}());
|
||||
return child.hitTest(result, position: transformed);
|
||||
return child!.hitTest(result, position: transformed!);
|
||||
},
|
||||
);
|
||||
if (isHit) {
|
||||
|
@ -476,18 +473,17 @@ class RenderParagraph extends RenderBox
|
|||
_layoutTextWithConstraints(constraints);
|
||||
final Offset offset = entry.localPosition;
|
||||
final TextPosition position = _textPainter.getPositionForOffset(offset);
|
||||
final InlineSpan span = _textPainter.text.getSpanForPosition(position);
|
||||
final InlineSpan? span = _textPainter.text!.getSpanForPosition(position);
|
||||
if (span == null) {
|
||||
return;
|
||||
}
|
||||
if (span is TextSpan) {
|
||||
final TextSpan textSpan = span;
|
||||
textSpan.recognizer?.addPointer(event as PointerDownEvent);
|
||||
span.recognizer?.addPointer(event);
|
||||
}
|
||||
}
|
||||
|
||||
bool _needsClipping = false;
|
||||
ui.Shader _overflowShader;
|
||||
ui.Shader? _overflowShader;
|
||||
|
||||
/// Whether this paragraph currently has a [dart:ui.Shader] for its overflow
|
||||
/// effect.
|
||||
|
@ -517,7 +513,7 @@ class RenderParagraph extends RenderBox
|
|||
// These need to be cached because the text painter's placeholder dimensions
|
||||
// will be overwritten during intrinsic width/height calculations and must be
|
||||
// restored to the original values before final layout and painting.
|
||||
List<PlaceholderDimensions> _placeholderDimensions;
|
||||
List<PlaceholderDimensions>? _placeholderDimensions;
|
||||
|
||||
void _layoutTextWithConstraints(BoxConstraints constraints) {
|
||||
_textPainter.setPlaceholderDimensions(_placeholderDimensions);
|
||||
|
@ -532,8 +528,8 @@ class RenderParagraph extends RenderBox
|
|||
if (childCount == 0) {
|
||||
return;
|
||||
}
|
||||
RenderBox child = firstChild;
|
||||
_placeholderDimensions = List<PlaceholderDimensions>(childCount);
|
||||
RenderBox? child = firstChild;
|
||||
final List<PlaceholderDimensions> placeholderDimensions = List<PlaceholderDimensions>.filled(childCount, PlaceholderDimensions.empty, growable: false);
|
||||
int childIndex = 0;
|
||||
BoxConstraints boxConstraints = BoxConstraints(maxWidth: constraints.maxWidth);
|
||||
// The content will be enlarged by textScaleFactor during painting phase.
|
||||
|
@ -547,11 +543,11 @@ class RenderParagraph extends RenderBox
|
|||
boxConstraints,
|
||||
parentUsesSize: true,
|
||||
);
|
||||
double baselineOffset;
|
||||
double? baselineOffset;
|
||||
switch (_placeholderSpans[childIndex].alignment) {
|
||||
case ui.PlaceholderAlignment.baseline: {
|
||||
baselineOffset = child.getDistanceToBaseline(
|
||||
_placeholderSpans[childIndex].baseline
|
||||
_placeholderSpans[childIndex].baseline!
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -560,7 +556,7 @@ class RenderParagraph extends RenderBox
|
|||
break;
|
||||
}
|
||||
}
|
||||
_placeholderDimensions[childIndex] = PlaceholderDimensions(
|
||||
placeholderDimensions[childIndex] = PlaceholderDimensions(
|
||||
size: child.size,
|
||||
alignment: _placeholderSpans[childIndex].alignment,
|
||||
baseline: _placeholderSpans[childIndex].baseline,
|
||||
|
@ -569,20 +565,21 @@ class RenderParagraph extends RenderBox
|
|||
child = childAfter(child);
|
||||
childIndex += 1;
|
||||
}
|
||||
_placeholderDimensions = placeholderDimensions.cast<PlaceholderDimensions>();
|
||||
}
|
||||
|
||||
// Iterate through the laid-out children and set the parentData offsets based
|
||||
// off of the placeholders inserted for each child.
|
||||
void _setParentData() {
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
int childIndex = 0;
|
||||
while (child != null && childIndex < _textPainter.inlinePlaceholderBoxes.length) {
|
||||
while (child != null && childIndex < _textPainter.inlinePlaceholderBoxes!.length) {
|
||||
final TextParentData textParentData = child.parentData as TextParentData;
|
||||
textParentData.offset = Offset(
|
||||
_textPainter.inlinePlaceholderBoxes[childIndex].left,
|
||||
_textPainter.inlinePlaceholderBoxes[childIndex].top,
|
||||
_textPainter.inlinePlaceholderBoxes![childIndex].left,
|
||||
_textPainter.inlinePlaceholderBoxes![childIndex].top,
|
||||
);
|
||||
textParentData.scale = _textPainter.inlinePlaceholderScales[childIndex];
|
||||
textParentData.scale = _textPainter.inlinePlaceholderScales![childIndex];
|
||||
child = childAfter(child);
|
||||
childIndex += 1;
|
||||
}
|
||||
|
@ -627,7 +624,7 @@ class RenderParagraph extends RenderBox
|
|||
assert(textDirection != null);
|
||||
_needsClipping = true;
|
||||
final TextPainter fadeSizePainter = TextPainter(
|
||||
text: TextSpan(style: _textPainter.text.style, text: '\u2026'),
|
||||
text: TextSpan(style: _textPainter.text!.style, text: '\u2026'),
|
||||
textDirection: textDirection,
|
||||
textScaleFactor: textScaleFactor,
|
||||
locale: locale,
|
||||
|
@ -702,23 +699,23 @@ class RenderParagraph extends RenderBox
|
|||
}
|
||||
_textPainter.paint(context.canvas, offset);
|
||||
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
int childIndex = 0;
|
||||
// childIndex might be out of index of placeholder boxes. This can happen
|
||||
// if engine truncates children due to ellipsis. Sadly, we would not know
|
||||
// it until we finish layout, and RenderObject is in immutable state at
|
||||
// this point.
|
||||
while (child != null && childIndex < _textPainter.inlinePlaceholderBoxes.length) {
|
||||
while (child != null && childIndex < _textPainter.inlinePlaceholderBoxes!.length) {
|
||||
final TextParentData textParentData = child.parentData as TextParentData;
|
||||
|
||||
final double scale = textParentData.scale;
|
||||
final double scale = textParentData.scale!;
|
||||
context.pushTransform(
|
||||
needsCompositing,
|
||||
offset + textParentData.offset,
|
||||
Matrix4.diagonal3Values(scale, scale, scale),
|
||||
(PaintingContext context, Offset offset) {
|
||||
context.paintChild(
|
||||
child,
|
||||
child!,
|
||||
offset,
|
||||
);
|
||||
},
|
||||
|
@ -800,7 +797,7 @@ class RenderParagraph extends RenderBox
|
|||
|
||||
/// Collected during [describeSemanticsConfiguration], used by
|
||||
/// [assembleSemanticsNode] and [_combineSemanticsInfo].
|
||||
List<InlineSpanSemanticsInformation> _semanticsInfo;
|
||||
List<InlineSpanSemanticsInformation>? _semanticsInfo;
|
||||
|
||||
/// Combines _semanticsInfo entries where permissible, determined by
|
||||
/// [InlineSpanSemanticsInformation.requiresOwnNode].
|
||||
|
@ -808,8 +805,10 @@ class RenderParagraph extends RenderBox
|
|||
assert(_semanticsInfo != null);
|
||||
final List<InlineSpanSemanticsInformation> combined = <InlineSpanSemanticsInformation>[];
|
||||
String workingText = '';
|
||||
String workingLabel;
|
||||
for (final InlineSpanSemanticsInformation info in _semanticsInfo) {
|
||||
// TODO(ianh): this algorithm is internally inconsistent. workingText
|
||||
// never becomes null, but we check for it being so below.
|
||||
String? workingLabel;
|
||||
for (final InlineSpanSemanticsInformation info in _semanticsInfo!) {
|
||||
if (info.requiresOwnNode) {
|
||||
if (workingText != null) {
|
||||
combined.add(InlineSpanSemanticsInformation(
|
||||
|
@ -824,7 +823,7 @@ class RenderParagraph extends RenderBox
|
|||
workingText += info.text;
|
||||
workingLabel ??= '';
|
||||
if (info.semanticsLabel != null) {
|
||||
workingLabel += info.semanticsLabel;
|
||||
workingLabel += info.semanticsLabel!;
|
||||
} else {
|
||||
workingLabel += info.text;
|
||||
}
|
||||
|
@ -835,7 +834,7 @@ class RenderParagraph extends RenderBox
|
|||
workingText,
|
||||
semanticsLabel: workingLabel,
|
||||
));
|
||||
} else {
|
||||
} else { // ignore: dead_code
|
||||
assert(workingLabel != null);
|
||||
}
|
||||
return combined;
|
||||
|
@ -846,12 +845,12 @@ class RenderParagraph extends RenderBox
|
|||
super.describeSemanticsConfiguration(config);
|
||||
_semanticsInfo = text.getSemanticsInformation();
|
||||
|
||||
if (_semanticsInfo.any((InlineSpanSemanticsInformation info) => info.recognizer != null)) {
|
||||
if (_semanticsInfo!.any((InlineSpanSemanticsInformation info) => info.recognizer != null)) {
|
||||
config.explicitChildNodes = true;
|
||||
config.isSemanticBoundary = true;
|
||||
} else {
|
||||
final StringBuffer buffer = StringBuffer();
|
||||
for (final InlineSpanSemanticsInformation info in _semanticsInfo) {
|
||||
for (final InlineSpanSemanticsInformation info in _semanticsInfo!) {
|
||||
buffer.write(info.semanticsLabel ?? info.text);
|
||||
}
|
||||
config.label = buffer.toString();
|
||||
|
@ -863,18 +862,18 @@ class RenderParagraph extends RenderBox
|
|||
// can be re-used when [assembleSemanticsNode] is called again. This ensures
|
||||
// stable ids for the [SemanticsNode]s of [TextSpan]s across
|
||||
// [assembleSemanticsNode] invocations.
|
||||
Queue<SemanticsNode> _cachedChildNodes;
|
||||
Queue<SemanticsNode>? _cachedChildNodes;
|
||||
|
||||
@override
|
||||
void assembleSemanticsNode(SemanticsNode node, SemanticsConfiguration config, Iterable<SemanticsNode> children) {
|
||||
assert(_semanticsInfo != null && _semanticsInfo.isNotEmpty);
|
||||
assert(_semanticsInfo != null && _semanticsInfo!.isNotEmpty);
|
||||
final List<SemanticsNode> newChildren = <SemanticsNode>[];
|
||||
TextDirection currentDirection = textDirection;
|
||||
Rect currentRect;
|
||||
double ordinal = 0.0;
|
||||
int start = 0;
|
||||
int placeholderIndex = 0;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
final Queue<SemanticsNode> newChildCache = Queue<SemanticsNode>();
|
||||
for (final InlineSpanSemanticsInformation info in _combineSemanticsInfo()) {
|
||||
final TextDirection initialDirection = currentDirection;
|
||||
|
@ -911,12 +910,12 @@ class RenderParagraph extends RenderBox
|
|||
|
||||
if (info.isPlaceholder) {
|
||||
final SemanticsNode childNode = children.elementAt(placeholderIndex++);
|
||||
final TextParentData parentData = child.parentData as TextParentData;
|
||||
final TextParentData parentData = child!.parentData as TextParentData;
|
||||
childNode.rect = Rect.fromLTWH(
|
||||
childNode.rect.left,
|
||||
childNode.rect.top,
|
||||
childNode.rect.width * parentData.scale,
|
||||
childNode.rect.height * parentData.scale,
|
||||
childNode.rect.width * parentData.scale!,
|
||||
childNode.rect.height * parentData.scale!,
|
||||
);
|
||||
newChildren.add(childNode);
|
||||
child = childAfter(child);
|
||||
|
@ -925,7 +924,7 @@ class RenderParagraph extends RenderBox
|
|||
..sortKey = OrdinalSortKey(ordinal++)
|
||||
..textDirection = initialDirection
|
||||
..label = info.semanticsLabel ?? info.text;
|
||||
final GestureRecognizer recognizer = info.recognizer;
|
||||
final GestureRecognizer? recognizer = info.recognizer;
|
||||
if (recognizer != null) {
|
||||
if (recognizer is TapGestureRecognizer) {
|
||||
configuration.onTap = recognizer.onTap;
|
||||
|
@ -940,7 +939,7 @@ class RenderParagraph extends RenderBox
|
|||
}
|
||||
}
|
||||
final SemanticsNode newChild = (_cachedChildNodes?.isNotEmpty == true)
|
||||
? _cachedChildNodes.removeFirst()
|
||||
? _cachedChildNodes!.removeFirst()
|
||||
: SemanticsNode();
|
||||
newChild
|
||||
..updateWith(config: configuration)
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'box.dart';
|
||||
import 'layer.dart';
|
||||
import 'object.dart';
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:ui';
|
||||
|
||||
|
@ -41,7 +39,7 @@ enum _PlatformViewState {
|
|||
ready,
|
||||
}
|
||||
|
||||
bool _factoryTypesSetEquals<T>(Set<Factory<T>> a, Set<Factory<T>> b) {
|
||||
bool _factoryTypesSetEquals<T>(Set<Factory<T>>? a, Set<Factory<T>>? b) {
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
|
@ -83,9 +81,9 @@ class RenderAndroidView extends RenderBox with _PlatformViewGestureMixin {
|
|||
|
||||
/// Creates a render object for an Android view.
|
||||
RenderAndroidView({
|
||||
@required AndroidViewController viewController,
|
||||
@required PlatformViewHitTestBehavior hitTestBehavior,
|
||||
@required Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
|
||||
required AndroidViewController viewController,
|
||||
required PlatformViewHitTestBehavior hitTestBehavior,
|
||||
required Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
|
||||
}) : assert(viewController != null),
|
||||
assert(hitTestBehavior != null),
|
||||
assert(gestureRecognizers != null),
|
||||
|
@ -157,7 +155,7 @@ class RenderAndroidView extends RenderBox with _PlatformViewGestureMixin {
|
|||
_sizePlatformView();
|
||||
}
|
||||
|
||||
Size _currentAndroidViewSize;
|
||||
late Size _currentAndroidViewSize;
|
||||
|
||||
Future<void> _sizePlatformView() async {
|
||||
// Android virtual displays cannot have a zero size.
|
||||
|
@ -211,7 +209,7 @@ class RenderAndroidView extends RenderBox with _PlatformViewGestureMixin {
|
|||
// _currentAndroidViewSize.
|
||||
context.addLayer(TextureLayer(
|
||||
rect: offset & _currentAndroidViewSize,
|
||||
textureId: _viewController.textureId,
|
||||
textureId: _viewController.textureId!,
|
||||
freeze: _state == _PlatformViewState.resizing,
|
||||
));
|
||||
}
|
||||
|
@ -255,9 +253,9 @@ class RenderUiKitView extends RenderBox {
|
|||
///
|
||||
/// The `viewId`, `hitTestBehavior`, and `gestureRecognizers` parameters must not be null.
|
||||
RenderUiKitView({
|
||||
@required UiKitViewController viewController,
|
||||
@required this.hitTestBehavior,
|
||||
@required Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
|
||||
required UiKitViewController viewController,
|
||||
required this.hitTestBehavior,
|
||||
required Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
|
||||
}) : assert(viewController != null),
|
||||
assert(hitTestBehavior != null),
|
||||
assert(gestureRecognizers != null),
|
||||
|
@ -310,9 +308,9 @@ class RenderUiKitView extends RenderBox {
|
|||
@override
|
||||
bool get isRepaintBoundary => true;
|
||||
|
||||
_UiKitViewGestureRecognizer _gestureRecognizer;
|
||||
_UiKitViewGestureRecognizer? _gestureRecognizer;
|
||||
|
||||
PointerEvent _lastPointerDownEvent;
|
||||
PointerEvent? _lastPointerDownEvent;
|
||||
|
||||
@override
|
||||
void performResize() {
|
||||
|
@ -328,8 +326,8 @@ class RenderUiKitView extends RenderBox {
|
|||
}
|
||||
|
||||
@override
|
||||
bool hitTest(BoxHitTestResult result, { Offset position }) {
|
||||
if (hitTestBehavior == PlatformViewHitTestBehavior.transparent || !size.contains(position))
|
||||
bool hitTest(BoxHitTestResult result, { Offset? position }) {
|
||||
if (hitTestBehavior == PlatformViewHitTestBehavior.transparent || !size.contains(position!))
|
||||
return false;
|
||||
result.add(BoxHitTestEntry(this, position));
|
||||
return hitTestBehavior == PlatformViewHitTestBehavior.opaque;
|
||||
|
@ -343,7 +341,7 @@ class RenderUiKitView extends RenderBox {
|
|||
if (event is! PointerDownEvent) {
|
||||
return;
|
||||
}
|
||||
_gestureRecognizer.addPointer(event as PointerDownEvent);
|
||||
_gestureRecognizer!.addPointer(event);
|
||||
_lastPointerDownEvent = event.original ?? event;
|
||||
}
|
||||
|
||||
|
@ -375,13 +373,13 @@ class RenderUiKitView extends RenderBox {
|
|||
@override
|
||||
void attach(PipelineOwner owner) {
|
||||
super.attach(owner);
|
||||
GestureBinding.instance.pointerRouter.addGlobalRoute(_handleGlobalPointerEvent);
|
||||
GestureBinding.instance!.pointerRouter.addGlobalRoute(_handleGlobalPointerEvent);
|
||||
}
|
||||
|
||||
@override
|
||||
void detach() {
|
||||
GestureBinding.instance.pointerRouter.removeGlobalRoute(_handleGlobalPointerEvent);
|
||||
_gestureRecognizer.reset();
|
||||
GestureBinding.instance!.pointerRouter.removeGlobalRoute(_handleGlobalPointerEvent);
|
||||
_gestureRecognizer!.reset();
|
||||
super.detach();
|
||||
}
|
||||
}
|
||||
|
@ -395,10 +393,10 @@ class _UiKitViewGestureRecognizer extends OneSequenceGestureRecognizer {
|
|||
_UiKitViewGestureRecognizer(
|
||||
this.controller,
|
||||
this.gestureRecognizerFactories, {
|
||||
PointerDeviceKind kind,
|
||||
PointerDeviceKind? kind,
|
||||
}) : super(kind: kind) {
|
||||
team = GestureArenaTeam();
|
||||
team.captain = this;
|
||||
team = GestureArenaTeam()
|
||||
..captain = this;
|
||||
_gestureRecognizers = gestureRecognizerFactories.map(
|
||||
(Factory<OneSequenceGestureRecognizer> recognizerFactory) {
|
||||
final OneSequenceGestureRecognizer gestureRecognizer = recognizerFactory.constructor();
|
||||
|
@ -423,7 +421,7 @@ class _UiKitViewGestureRecognizer extends OneSequenceGestureRecognizer {
|
|||
// TODO(amirh): get a list of GestureRecognizers here.
|
||||
// https://github.com/flutter/flutter/issues/20953
|
||||
final Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizerFactories;
|
||||
Set<OneSequenceGestureRecognizer> _gestureRecognizers;
|
||||
late Set<OneSequenceGestureRecognizer> _gestureRecognizers;
|
||||
|
||||
final UiKitViewController controller;
|
||||
|
||||
|
@ -473,10 +471,10 @@ class _PlatformViewGestureRecognizer extends OneSequenceGestureRecognizer {
|
|||
_PlatformViewGestureRecognizer(
|
||||
_HandlePointerEvent handlePointerEvent,
|
||||
this.gestureRecognizerFactories, {
|
||||
PointerDeviceKind kind,
|
||||
PointerDeviceKind? kind,
|
||||
}) : super(kind: kind) {
|
||||
team = GestureArenaTeam();
|
||||
team.captain = this;
|
||||
team = GestureArenaTeam()
|
||||
..captain = this;
|
||||
_gestureRecognizers = gestureRecognizerFactories.map(
|
||||
(Factory<OneSequenceGestureRecognizer> recognizerFactory) {
|
||||
final OneSequenceGestureRecognizer gestureRecognizer = recognizerFactory.constructor();
|
||||
|
@ -497,7 +495,7 @@ class _PlatformViewGestureRecognizer extends OneSequenceGestureRecognizer {
|
|||
_handlePointerEvent = handlePointerEvent;
|
||||
}
|
||||
|
||||
_HandlePointerEvent _handlePointerEvent;
|
||||
late _HandlePointerEvent _handlePointerEvent;
|
||||
|
||||
// Maps a pointer to a list of its cached pointer events.
|
||||
// Before the arena for a pointer is resolved all events are cached here, if we win the arena
|
||||
|
@ -513,7 +511,7 @@ class _PlatformViewGestureRecognizer extends OneSequenceGestureRecognizer {
|
|||
// TODO(amirh): get a list of GestureRecognizers here.
|
||||
// https://github.com/flutter/flutter/issues/20953
|
||||
final Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizerFactories;
|
||||
Set<OneSequenceGestureRecognizer> _gestureRecognizers;
|
||||
late Set<OneSequenceGestureRecognizer> _gestureRecognizers;
|
||||
|
||||
@override
|
||||
void addAllowedPointer(PointerDownEvent event) {
|
||||
|
@ -555,7 +553,7 @@ class _PlatformViewGestureRecognizer extends OneSequenceGestureRecognizer {
|
|||
if (!cachedEvents.containsKey(event.pointer)) {
|
||||
cachedEvents[event.pointer] = <PointerEvent> [];
|
||||
}
|
||||
cachedEvents[event.pointer].add(event);
|
||||
cachedEvents[event.pointer]!.add(event);
|
||||
}
|
||||
|
||||
void _flushPointerCache(int pointer) {
|
||||
|
@ -587,9 +585,9 @@ class PlatformViewRenderBox extends RenderBox with _PlatformViewGestureMixin {
|
|||
///
|
||||
/// The `controller` parameter must not be null.
|
||||
PlatformViewRenderBox({
|
||||
@required PlatformViewController controller,
|
||||
@required PlatformViewHitTestBehavior hitTestBehavior,
|
||||
@required Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
|
||||
required PlatformViewController controller,
|
||||
required PlatformViewHitTestBehavior hitTestBehavior,
|
||||
required Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers,
|
||||
}) : assert(controller != null && controller.viewId != null && controller.viewId > -1),
|
||||
assert(hitTestBehavior != null),
|
||||
assert(gestureRecognizers != null),
|
||||
|
@ -670,9 +668,9 @@ mixin _PlatformViewGestureMixin on RenderBox implements MouseTrackerAnnotation {
|
|||
markNeedsPaint();
|
||||
}
|
||||
}
|
||||
PlatformViewHitTestBehavior _hitTestBehavior;
|
||||
PlatformViewHitTestBehavior? _hitTestBehavior;
|
||||
|
||||
_HandlePointerEvent _handlePointerEvent;
|
||||
_HandlePointerEvent? _handlePointerEvent;
|
||||
|
||||
/// {@macro flutter.rendering.platformView.updateGestureRecognizers}
|
||||
///
|
||||
|
@ -692,10 +690,10 @@ mixin _PlatformViewGestureMixin on RenderBox implements MouseTrackerAnnotation {
|
|||
_handlePointerEvent = handlePointerEvent;
|
||||
}
|
||||
|
||||
_PlatformViewGestureRecognizer _gestureRecognizer;
|
||||
_PlatformViewGestureRecognizer? _gestureRecognizer;
|
||||
|
||||
@override
|
||||
bool hitTest(BoxHitTestResult result, { Offset position }) {
|
||||
bool hitTest(BoxHitTestResult result, { required Offset position }) {
|
||||
if (_hitTestBehavior == PlatformViewHitTestBehavior.transparent || !size.contains(position)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -707,17 +705,17 @@ mixin _PlatformViewGestureMixin on RenderBox implements MouseTrackerAnnotation {
|
|||
bool hitTestSelf(Offset position) => _hitTestBehavior != PlatformViewHitTestBehavior.transparent;
|
||||
|
||||
@override
|
||||
PointerEnterEventListener get onEnter => null;
|
||||
PointerEnterEventListener? get onEnter => null;
|
||||
|
||||
@override
|
||||
PointerHoverEventListener get onHover => _handleHover;
|
||||
void _handleHover(PointerHoverEvent event) {
|
||||
if (_handlePointerEvent != null)
|
||||
_handlePointerEvent(event);
|
||||
_handlePointerEvent!(event);
|
||||
}
|
||||
|
||||
@override
|
||||
PointerExitEventListener get onExit => null;
|
||||
PointerExitEventListener? get onExit => null;
|
||||
|
||||
@override
|
||||
MouseCursor get cursor => MouseCursor.uncontrolled;
|
||||
|
@ -725,13 +723,13 @@ mixin _PlatformViewGestureMixin on RenderBox implements MouseTrackerAnnotation {
|
|||
@override
|
||||
void handleEvent(PointerEvent event, HitTestEntry entry) {
|
||||
if (event is PointerDownEvent) {
|
||||
_gestureRecognizer.addPointer(event);
|
||||
_gestureRecognizer!.addPointer(event);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void detach() {
|
||||
_gestureRecognizer.reset();
|
||||
_gestureRecognizer!.reset();
|
||||
super.detach();
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:ui' as ui show Color;
|
||||
|
||||
import 'package:flutter/animation.dart';
|
||||
|
@ -38,7 +36,7 @@ abstract class RenderProxySliver extends RenderSliver with RenderObjectWithChild
|
|||
/// Proxy render slivers aren't created directly because they simply proxy
|
||||
/// the render sliver protocol to their sliver [child]. Instead, use one of
|
||||
/// the subclasses.
|
||||
RenderProxySliver([RenderSliver child]) {
|
||||
RenderProxySliver([RenderSliver? child]) {
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
|
@ -51,21 +49,21 @@ abstract class RenderProxySliver extends RenderSliver with RenderObjectWithChild
|
|||
@override
|
||||
void performLayout() {
|
||||
assert(child != null);
|
||||
child.layout(constraints, parentUsesSize: true);
|
||||
geometry = child.geometry;
|
||||
child!.layout(constraints, parentUsesSize: true);
|
||||
geometry = child!.geometry;
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
if (child != null)
|
||||
context.paintChild(child, offset);
|
||||
context.paintChild(child!, offset);
|
||||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(SliverHitTestResult result, {double mainAxisPosition, double crossAxisPosition}) {
|
||||
bool hitTestChildren(SliverHitTestResult result, {required double mainAxisPosition, required double crossAxisPosition}) {
|
||||
return child != null
|
||||
&& child.geometry.hitTestExtent > 0
|
||||
&& child.hitTest(
|
||||
&& child!.geometry!.hitTestExtent > 0
|
||||
&& child!.hitTest(
|
||||
result,
|
||||
mainAxisPosition: mainAxisPosition,
|
||||
crossAxisPosition: crossAxisPosition,
|
||||
|
@ -104,7 +102,7 @@ class RenderSliverOpacity extends RenderProxySliver {
|
|||
RenderSliverOpacity({
|
||||
double opacity = 1.0,
|
||||
bool alwaysIncludeSemantics = false,
|
||||
RenderSliver sliver,
|
||||
RenderSliver? sliver,
|
||||
}) : assert(opacity != null && opacity >= 0.0 && opacity <= 1.0),
|
||||
assert(alwaysIncludeSemantics != null),
|
||||
_opacity = opacity,
|
||||
|
@ -162,7 +160,7 @@ class RenderSliverOpacity extends RenderProxySliver {
|
|||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
if (child != null && child.geometry.visible) {
|
||||
if (child != null && child!.geometry!.visible) {
|
||||
if (_alpha == 0) {
|
||||
// No need to keep the layer. We'll create a new one if necessary.
|
||||
layer = null;
|
||||
|
@ -171,7 +169,7 @@ class RenderSliverOpacity extends RenderProxySliver {
|
|||
if (_alpha == 255) {
|
||||
// No need to keep the layer. We'll create a new one if necessary.
|
||||
layer = null;
|
||||
context.paintChild(child, offset);
|
||||
context.paintChild(child!, offset);
|
||||
return;
|
||||
}
|
||||
assert(needsCompositing);
|
||||
|
@ -187,7 +185,7 @@ class RenderSliverOpacity extends RenderProxySliver {
|
|||
@override
|
||||
void visitChildrenForSemantics(RenderObjectVisitor visitor) {
|
||||
if (child != null && (_alpha != 0 || alwaysIncludeSemantics))
|
||||
visitor(child);
|
||||
visitor(child!);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -214,9 +212,9 @@ class RenderSliverIgnorePointer extends RenderProxySliver {
|
|||
/// The [ignoring] argument must not be null. If [ignoringSemantics] is null,
|
||||
/// this render object will be ignored for semantics if [ignoring] is true.
|
||||
RenderSliverIgnorePointer({
|
||||
RenderSliver sliver,
|
||||
RenderSliver? sliver,
|
||||
bool ignoring = true,
|
||||
bool ignoringSemantics,
|
||||
bool? ignoringSemantics,
|
||||
}) : assert(ignoring != null),
|
||||
_ignoring = ignoring,
|
||||
_ignoringSemantics = ignoringSemantics {
|
||||
|
@ -234,7 +232,7 @@ class RenderSliverIgnorePointer extends RenderProxySliver {
|
|||
if (value == _ignoring)
|
||||
return;
|
||||
_ignoring = value;
|
||||
if (_ignoringSemantics == null || !_ignoringSemantics)
|
||||
if (_ignoringSemantics == null || !_ignoringSemantics!)
|
||||
markNeedsSemanticsUpdate();
|
||||
}
|
||||
|
||||
|
@ -244,9 +242,9 @@ class RenderSliverIgnorePointer extends RenderProxySliver {
|
|||
/// If null, defaults to value of [ignoring].
|
||||
///
|
||||
/// See [SemanticsNode] for additional information about the semantics tree.
|
||||
bool get ignoringSemantics => _ignoringSemantics;
|
||||
bool _ignoringSemantics;
|
||||
set ignoringSemantics(bool value) {
|
||||
bool? get ignoringSemantics => _ignoringSemantics;
|
||||
bool? _ignoringSemantics;
|
||||
set ignoringSemantics(bool? value) {
|
||||
if (value == _ignoringSemantics)
|
||||
return;
|
||||
final bool oldEffectiveValue = _effectiveIgnoringSemantics;
|
||||
|
@ -258,7 +256,7 @@ class RenderSliverIgnorePointer extends RenderProxySliver {
|
|||
bool get _effectiveIgnoringSemantics => ignoringSemantics ?? ignoring;
|
||||
|
||||
@override
|
||||
bool hitTest(SliverHitTestResult result, {double mainAxisPosition, double crossAxisPosition}) {
|
||||
bool hitTest(SliverHitTestResult result, {required double mainAxisPosition, required double crossAxisPosition}) {
|
||||
return !ignoring
|
||||
&& super.hitTest(
|
||||
result,
|
||||
|
@ -270,7 +268,7 @@ class RenderSliverIgnorePointer extends RenderProxySliver {
|
|||
@override
|
||||
void visitChildrenForSemantics(RenderObjectVisitor visitor) {
|
||||
if (child != null && !_effectiveIgnoringSemantics)
|
||||
visitor(child);
|
||||
visitor(child!);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -288,7 +286,7 @@ class RenderSliverOffstage extends RenderProxySliver {
|
|||
/// Creates an offstage render object.
|
||||
RenderSliverOffstage({
|
||||
bool offstage = true,
|
||||
RenderSliver sliver,
|
||||
RenderSliver? sliver,
|
||||
}) : assert(offstage != null),
|
||||
_offstage = offstage {
|
||||
child = sliver;
|
||||
|
@ -315,9 +313,9 @@ class RenderSliverOffstage extends RenderProxySliver {
|
|||
@override
|
||||
void performLayout() {
|
||||
assert(child != null);
|
||||
child.layout(constraints, parentUsesSize: true);
|
||||
child!.layout(constraints, parentUsesSize: true);
|
||||
if (!offstage)
|
||||
geometry = child.geometry;
|
||||
geometry = child!.geometry;
|
||||
else
|
||||
geometry = const SliverGeometry(
|
||||
scrollExtent: 0.0,
|
||||
|
@ -327,7 +325,7 @@ class RenderSliverOffstage extends RenderProxySliver {
|
|||
}
|
||||
|
||||
@override
|
||||
bool hitTest(SliverHitTestResult result, {double mainAxisPosition, double crossAxisPosition}) {
|
||||
bool hitTest(SliverHitTestResult result, {required double mainAxisPosition, required double crossAxisPosition}) {
|
||||
return !offstage && super.hitTest(
|
||||
result,
|
||||
mainAxisPosition: mainAxisPosition,
|
||||
|
@ -336,11 +334,11 @@ class RenderSliverOffstage extends RenderProxySliver {
|
|||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(SliverHitTestResult result, {double mainAxisPosition, double crossAxisPosition}) {
|
||||
bool hitTestChildren(SliverHitTestResult result, {required double mainAxisPosition, required double crossAxisPosition}) {
|
||||
return !offstage
|
||||
&& child != null
|
||||
&& child.geometry.hitTestExtent > 0
|
||||
&& child.hitTest(
|
||||
&& child!.geometry!.hitTestExtent > 0
|
||||
&& child!.hitTest(
|
||||
result,
|
||||
mainAxisPosition: mainAxisPosition,
|
||||
crossAxisPosition: crossAxisPosition,
|
||||
|
@ -351,7 +349,7 @@ class RenderSliverOffstage extends RenderProxySliver {
|
|||
void paint(PaintingContext context, Offset offset) {
|
||||
if (offstage)
|
||||
return;
|
||||
context.paintChild(child, offset);
|
||||
context.paintChild(child!, offset);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -372,7 +370,7 @@ class RenderSliverOffstage extends RenderProxySliver {
|
|||
if (child == null)
|
||||
return <DiagnosticsNode>[];
|
||||
return <DiagnosticsNode>[
|
||||
child.toDiagnosticsNode(
|
||||
child!.toDiagnosticsNode(
|
||||
name: 'child',
|
||||
style: offstage ? DiagnosticsTreeStyle.offstage : DiagnosticsTreeStyle.sparse,
|
||||
),
|
||||
|
@ -389,9 +387,9 @@ class RenderSliverAnimatedOpacity extends RenderProxySliver with RenderAnimatedO
|
|||
///
|
||||
/// The [opacity] argument must not be null.
|
||||
RenderSliverAnimatedOpacity({
|
||||
@required Animation<double> opacity,
|
||||
required Animation<double> opacity,
|
||||
bool alwaysIncludeSemantics = false,
|
||||
RenderSliver sliver,
|
||||
RenderSliver? sliver,
|
||||
}) : assert(opacity != null),
|
||||
assert(alwaysIncludeSemantics != null) {
|
||||
this.opacity = opacity;
|
||||
|
|
|
@ -2,11 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/painting.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
@ -26,8 +23,8 @@ class RenderRotatedBox extends RenderBox with RenderObjectWithChildMixin<RenderB
|
|||
///
|
||||
/// The [quarterTurns] argument must not be null.
|
||||
RenderRotatedBox({
|
||||
@required int quarterTurns,
|
||||
RenderBox child,
|
||||
required int quarterTurns,
|
||||
RenderBox? child,
|
||||
}) : assert(quarterTurns != null),
|
||||
_quarterTurns = quarterTurns {
|
||||
this.child = child;
|
||||
|
@ -50,75 +47,75 @@ class RenderRotatedBox extends RenderBox with RenderObjectWithChildMixin<RenderB
|
|||
double computeMinIntrinsicWidth(double height) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
return _isVertical ? child.getMinIntrinsicHeight(height) : child.getMinIntrinsicWidth(height);
|
||||
return _isVertical ? child!.getMinIntrinsicHeight(height) : child!.getMinIntrinsicWidth(height);
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
return _isVertical ? child.getMaxIntrinsicHeight(height) : child.getMaxIntrinsicWidth(height);
|
||||
return _isVertical ? child!.getMaxIntrinsicHeight(height) : child!.getMaxIntrinsicWidth(height);
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
return _isVertical ? child.getMinIntrinsicWidth(width) : child.getMinIntrinsicHeight(width);
|
||||
return _isVertical ? child!.getMinIntrinsicWidth(width) : child!.getMinIntrinsicHeight(width);
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
return _isVertical ? child.getMaxIntrinsicWidth(width) : child.getMaxIntrinsicHeight(width);
|
||||
return _isVertical ? child!.getMaxIntrinsicWidth(width) : child!.getMaxIntrinsicHeight(width);
|
||||
}
|
||||
|
||||
Matrix4 _paintTransform;
|
||||
Matrix4? _paintTransform;
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
_paintTransform = null;
|
||||
if (child != null) {
|
||||
child.layout(_isVertical ? constraints.flipped : constraints, parentUsesSize: true);
|
||||
size = _isVertical ? Size(child.size.height, child.size.width) : child.size;
|
||||
child!.layout(_isVertical ? constraints.flipped : constraints, parentUsesSize: true);
|
||||
size = _isVertical ? Size(child!.size.height, child!.size.width) : child!.size;
|
||||
_paintTransform = Matrix4.identity()
|
||||
..translate(size.width / 2.0, size.height / 2.0)
|
||||
..rotateZ(_kQuarterTurnsInRadians * (quarterTurns % 4))
|
||||
..translate(-child.size.width / 2.0, -child.size.height / 2.0);
|
||||
..translate(-child!.size.width / 2.0, -child!.size.height / 2.0);
|
||||
} else {
|
||||
performResize();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
|
||||
assert(_paintTransform != null || debugNeedsLayout || child == null);
|
||||
if (child == null || _paintTransform == null)
|
||||
return false;
|
||||
return result.addWithPaintTransform(
|
||||
transform: _paintTransform,
|
||||
position: position,
|
||||
hitTest: (BoxHitTestResult result, Offset position) {
|
||||
return child.hitTest(result, position: position);
|
||||
hitTest: (BoxHitTestResult result, Offset? position) {
|
||||
return child!.hitTest(result, position: position!);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _paintChild(PaintingContext context, Offset offset) {
|
||||
context.paintChild(child, offset);
|
||||
context.paintChild(child!, offset);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
if (child != null)
|
||||
context.pushTransform(needsCompositing, offset, _paintTransform, _paintChild);
|
||||
context.pushTransform(needsCompositing, offset, _paintTransform!, _paintChild);
|
||||
}
|
||||
|
||||
@override
|
||||
void applyPaintTransform(RenderBox child, Matrix4 transform) {
|
||||
if (_paintTransform != null)
|
||||
transform.multiply(_paintTransform);
|
||||
transform.multiply(_paintTransform!);
|
||||
super.applyPaintTransform(child, transform);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -18,45 +16,45 @@ import 'stack.dart' show RelativeRect;
|
|||
/// the child's position.
|
||||
abstract class RenderShiftedBox extends RenderBox with RenderObjectWithChildMixin<RenderBox> {
|
||||
/// Initializes the [child] property for subclasses.
|
||||
RenderShiftedBox(RenderBox child) {
|
||||
RenderShiftedBox(RenderBox? child) {
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
if (child != null)
|
||||
return child.getMinIntrinsicWidth(height);
|
||||
return child!.getMinIntrinsicWidth(height);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
if (child != null)
|
||||
return child.getMaxIntrinsicWidth(height);
|
||||
return child!.getMaxIntrinsicWidth(height);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
if (child != null)
|
||||
return child.getMinIntrinsicHeight(width);
|
||||
return child!.getMinIntrinsicHeight(width);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
if (child != null)
|
||||
return child.getMaxIntrinsicHeight(width);
|
||||
return child!.getMaxIntrinsicHeight(width);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
double result;
|
||||
double? computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
double? result;
|
||||
if (child != null) {
|
||||
assert(!debugNeedsLayout);
|
||||
result = child.getDistanceToActualBaseline(baseline);
|
||||
final BoxParentData childParentData = child.parentData as BoxParentData;
|
||||
result = child!.getDistanceToActualBaseline(baseline);
|
||||
final BoxParentData childParentData = child!.parentData as BoxParentData;
|
||||
if (result != null)
|
||||
result += childParentData.offset.dy;
|
||||
} else {
|
||||
|
@ -68,21 +66,21 @@ abstract class RenderShiftedBox extends RenderBox with RenderObjectWithChildMixi
|
|||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
if (child != null) {
|
||||
final BoxParentData childParentData = child.parentData as BoxParentData;
|
||||
context.paintChild(child, childParentData.offset + offset);
|
||||
final BoxParentData childParentData = child!.parentData as BoxParentData;
|
||||
context.paintChild(child!, childParentData.offset + offset);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
|
||||
if (child != null) {
|
||||
final BoxParentData childParentData = child.parentData as BoxParentData;
|
||||
final BoxParentData childParentData = child!.parentData as BoxParentData;
|
||||
return result.addWithPaintOffset(
|
||||
offset: childParentData.offset,
|
||||
position: position,
|
||||
hitTest: (BoxHitTestResult result, Offset transformed) {
|
||||
hitTest: (BoxHitTestResult result, Offset? transformed) {
|
||||
assert(transformed == position - childParentData.offset);
|
||||
return child.hitTest(result, position: transformed);
|
||||
return child!.hitTest(result, position: transformed!);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -102,22 +100,22 @@ class RenderPadding extends RenderShiftedBox {
|
|||
///
|
||||
/// The [padding] argument must not be null and must have non-negative insets.
|
||||
RenderPadding({
|
||||
@required EdgeInsetsGeometry padding,
|
||||
TextDirection textDirection,
|
||||
RenderBox child,
|
||||
required EdgeInsetsGeometry padding,
|
||||
TextDirection? textDirection,
|
||||
RenderBox? child,
|
||||
}) : assert(padding != null),
|
||||
assert(padding.isNonNegative),
|
||||
_textDirection = textDirection,
|
||||
_padding = padding,
|
||||
super(child);
|
||||
|
||||
EdgeInsets _resolvedPadding;
|
||||
EdgeInsets? _resolvedPadding;
|
||||
|
||||
void _resolve() {
|
||||
if (_resolvedPadding != null)
|
||||
return;
|
||||
_resolvedPadding = padding.resolve(textDirection);
|
||||
assert(_resolvedPadding.isNonNegative);
|
||||
assert(_resolvedPadding!.isNonNegative);
|
||||
}
|
||||
|
||||
void _markNeedResolution() {
|
||||
|
@ -144,9 +142,9 @@ class RenderPadding extends RenderShiftedBox {
|
|||
///
|
||||
/// This may be changed to null, but only after the [padding] has been changed
|
||||
/// to a value that does not depend on the direction.
|
||||
TextDirection get textDirection => _textDirection;
|
||||
TextDirection _textDirection;
|
||||
set textDirection(TextDirection value) {
|
||||
TextDirection? get textDirection => _textDirection;
|
||||
TextDirection? _textDirection;
|
||||
set textDirection(TextDirection? value) {
|
||||
if (_textDirection == value)
|
||||
return;
|
||||
_textDirection = value;
|
||||
|
@ -156,40 +154,40 @@ class RenderPadding extends RenderShiftedBox {
|
|||
@override
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
_resolve();
|
||||
final double totalHorizontalPadding = _resolvedPadding.left + _resolvedPadding.right;
|
||||
final double totalVerticalPadding = _resolvedPadding.top + _resolvedPadding.bottom;
|
||||
final double totalHorizontalPadding = _resolvedPadding!.left + _resolvedPadding!.right;
|
||||
final double totalVerticalPadding = _resolvedPadding!.top + _resolvedPadding!.bottom;
|
||||
if (child != null) // next line relies on double.infinity absorption
|
||||
return child.getMinIntrinsicWidth(math.max(0.0, height - totalVerticalPadding)) + totalHorizontalPadding;
|
||||
return child!.getMinIntrinsicWidth(math.max(0.0, height - totalVerticalPadding)) + totalHorizontalPadding;
|
||||
return totalHorizontalPadding;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
_resolve();
|
||||
final double totalHorizontalPadding = _resolvedPadding.left + _resolvedPadding.right;
|
||||
final double totalVerticalPadding = _resolvedPadding.top + _resolvedPadding.bottom;
|
||||
final double totalHorizontalPadding = _resolvedPadding!.left + _resolvedPadding!.right;
|
||||
final double totalVerticalPadding = _resolvedPadding!.top + _resolvedPadding!.bottom;
|
||||
if (child != null) // next line relies on double.infinity absorption
|
||||
return child.getMaxIntrinsicWidth(math.max(0.0, height - totalVerticalPadding)) + totalHorizontalPadding;
|
||||
return child!.getMaxIntrinsicWidth(math.max(0.0, height - totalVerticalPadding)) + totalHorizontalPadding;
|
||||
return totalHorizontalPadding;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
_resolve();
|
||||
final double totalHorizontalPadding = _resolvedPadding.left + _resolvedPadding.right;
|
||||
final double totalVerticalPadding = _resolvedPadding.top + _resolvedPadding.bottom;
|
||||
final double totalHorizontalPadding = _resolvedPadding!.left + _resolvedPadding!.right;
|
||||
final double totalVerticalPadding = _resolvedPadding!.top + _resolvedPadding!.bottom;
|
||||
if (child != null) // next line relies on double.infinity absorption
|
||||
return child.getMinIntrinsicHeight(math.max(0.0, width - totalHorizontalPadding)) + totalVerticalPadding;
|
||||
return child!.getMinIntrinsicHeight(math.max(0.0, width - totalHorizontalPadding)) + totalVerticalPadding;
|
||||
return totalVerticalPadding;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
_resolve();
|
||||
final double totalHorizontalPadding = _resolvedPadding.left + _resolvedPadding.right;
|
||||
final double totalVerticalPadding = _resolvedPadding.top + _resolvedPadding.bottom;
|
||||
final double totalHorizontalPadding = _resolvedPadding!.left + _resolvedPadding!.right;
|
||||
final double totalVerticalPadding = _resolvedPadding!.top + _resolvedPadding!.bottom;
|
||||
if (child != null) // next line relies on double.infinity absorption
|
||||
return child.getMaxIntrinsicHeight(math.max(0.0, width - totalHorizontalPadding)) + totalVerticalPadding;
|
||||
return child!.getMaxIntrinsicHeight(math.max(0.0, width - totalHorizontalPadding)) + totalVerticalPadding;
|
||||
return totalVerticalPadding;
|
||||
}
|
||||
|
||||
|
@ -200,18 +198,18 @@ class RenderPadding extends RenderShiftedBox {
|
|||
assert(_resolvedPadding != null);
|
||||
if (child == null) {
|
||||
size = constraints.constrain(Size(
|
||||
_resolvedPadding.left + _resolvedPadding.right,
|
||||
_resolvedPadding.top + _resolvedPadding.bottom,
|
||||
_resolvedPadding!.left + _resolvedPadding!.right,
|
||||
_resolvedPadding!.top + _resolvedPadding!.bottom,
|
||||
));
|
||||
return;
|
||||
}
|
||||
final BoxConstraints innerConstraints = constraints.deflate(_resolvedPadding);
|
||||
child.layout(innerConstraints, parentUsesSize: true);
|
||||
final BoxParentData childParentData = child.parentData as BoxParentData;
|
||||
childParentData.offset = Offset(_resolvedPadding.left, _resolvedPadding.top);
|
||||
final BoxConstraints innerConstraints = constraints.deflate(_resolvedPadding!);
|
||||
child!.layout(innerConstraints, parentUsesSize: true);
|
||||
final BoxParentData childParentData = child!.parentData as BoxParentData;
|
||||
childParentData.offset = Offset(_resolvedPadding!.left, _resolvedPadding!.top);
|
||||
size = constraints.constrain(Size(
|
||||
_resolvedPadding.left + child.size.width + _resolvedPadding.right,
|
||||
_resolvedPadding.top + child.size.height + _resolvedPadding.bottom,
|
||||
_resolvedPadding!.left + child!.size.width + _resolvedPadding!.right,
|
||||
_resolvedPadding!.top + child!.size.height + _resolvedPadding!.bottom,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -220,7 +218,7 @@ class RenderPadding extends RenderShiftedBox {
|
|||
super.debugPaintSize(context, offset);
|
||||
assert(() {
|
||||
final Rect outerRect = offset & size;
|
||||
debugPaintPadding(context.canvas, outerRect, child != null ? _resolvedPadding.deflateRect(outerRect) : null);
|
||||
debugPaintPadding(context.canvas, outerRect, child != null ? _resolvedPadding!.deflateRect(outerRect) : null);
|
||||
return true;
|
||||
}());
|
||||
}
|
||||
|
@ -244,8 +242,8 @@ abstract class RenderAligningShiftedBox extends RenderShiftedBox {
|
|||
/// direction-sensitive.
|
||||
RenderAligningShiftedBox({
|
||||
AlignmentGeometry alignment = Alignment.center,
|
||||
@required TextDirection textDirection,
|
||||
RenderBox child,
|
||||
required TextDirection? textDirection,
|
||||
RenderBox? child,
|
||||
}) : assert(alignment != null),
|
||||
_alignment = alignment,
|
||||
_textDirection = textDirection,
|
||||
|
@ -254,10 +252,10 @@ abstract class RenderAligningShiftedBox extends RenderShiftedBox {
|
|||
/// A constructor to be used only when the extending class also has a mixin.
|
||||
// TODO(gspencer): Remove this constructor once https://github.com/dart-lang/sdk/issues/31543 is fixed.
|
||||
@protected
|
||||
RenderAligningShiftedBox.mixin(AlignmentGeometry alignment, TextDirection textDirection, RenderBox child)
|
||||
RenderAligningShiftedBox.mixin(AlignmentGeometry alignment, TextDirection? textDirection, RenderBox? child)
|
||||
: this(alignment: alignment, textDirection: textDirection, child: child);
|
||||
|
||||
Alignment _resolvedAlignment;
|
||||
Alignment? _resolvedAlignment;
|
||||
|
||||
void _resolve() {
|
||||
if (_resolvedAlignment != null)
|
||||
|
@ -299,9 +297,9 @@ abstract class RenderAligningShiftedBox extends RenderShiftedBox {
|
|||
///
|
||||
/// This may be changed to null, but only after [alignment] has been changed
|
||||
/// to a value that does not depend on the direction.
|
||||
TextDirection get textDirection => _textDirection;
|
||||
TextDirection _textDirection;
|
||||
set textDirection(TextDirection value) {
|
||||
TextDirection? get textDirection => _textDirection;
|
||||
TextDirection? _textDirection;
|
||||
set textDirection(TextDirection? value) {
|
||||
if (_textDirection == value)
|
||||
return;
|
||||
_textDirection = value;
|
||||
|
@ -320,12 +318,12 @@ abstract class RenderAligningShiftedBox extends RenderShiftedBox {
|
|||
void alignChild() {
|
||||
_resolve();
|
||||
assert(child != null);
|
||||
assert(!child.debugNeedsLayout);
|
||||
assert(child.hasSize);
|
||||
assert(!child!.debugNeedsLayout);
|
||||
assert(child!.hasSize);
|
||||
assert(hasSize);
|
||||
assert(_resolvedAlignment != null);
|
||||
final BoxParentData childParentData = child.parentData as BoxParentData;
|
||||
childParentData.offset = _resolvedAlignment.alongOffset(size - child.size as Offset);
|
||||
final BoxParentData childParentData = child!.parentData as BoxParentData;
|
||||
childParentData.offset = _resolvedAlignment!.alongOffset(size - child!.size as Offset);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -349,11 +347,11 @@ abstract class RenderAligningShiftedBox extends RenderShiftedBox {
|
|||
class RenderPositionedBox extends RenderAligningShiftedBox {
|
||||
/// Creates a render object that positions its child.
|
||||
RenderPositionedBox({
|
||||
RenderBox child,
|
||||
double widthFactor,
|
||||
double heightFactor,
|
||||
RenderBox? child,
|
||||
double? widthFactor,
|
||||
double? heightFactor,
|
||||
AlignmentGeometry alignment = Alignment.center,
|
||||
TextDirection textDirection,
|
||||
TextDirection? textDirection,
|
||||
}) : assert(widthFactor == null || widthFactor >= 0.0),
|
||||
assert(heightFactor == null || heightFactor >= 0.0),
|
||||
_widthFactor = widthFactor,
|
||||
|
@ -363,9 +361,9 @@ class RenderPositionedBox extends RenderAligningShiftedBox {
|
|||
/// If non-null, sets its width to the child's width multiplied by this factor.
|
||||
///
|
||||
/// Can be both greater and less than 1.0 but must be positive.
|
||||
double get widthFactor => _widthFactor;
|
||||
double _widthFactor;
|
||||
set widthFactor(double value) {
|
||||
double? get widthFactor => _widthFactor;
|
||||
double? _widthFactor;
|
||||
set widthFactor(double? value) {
|
||||
assert(value == null || value >= 0.0);
|
||||
if (_widthFactor == value)
|
||||
return;
|
||||
|
@ -376,9 +374,9 @@ class RenderPositionedBox extends RenderAligningShiftedBox {
|
|||
/// If non-null, sets its height to the child's height multiplied by this factor.
|
||||
///
|
||||
/// Can be both greater and less than 1.0 but must be positive.
|
||||
double get heightFactor => _heightFactor;
|
||||
double _heightFactor;
|
||||
set heightFactor(double value) {
|
||||
double? get heightFactor => _heightFactor;
|
||||
double? _heightFactor;
|
||||
set heightFactor(double? value) {
|
||||
assert(value == null || value >= 0.0);
|
||||
if (_heightFactor == value)
|
||||
return;
|
||||
|
@ -393,9 +391,9 @@ class RenderPositionedBox extends RenderAligningShiftedBox {
|
|||
final bool shrinkWrapHeight = _heightFactor != null || constraints.maxHeight == double.infinity;
|
||||
|
||||
if (child != null) {
|
||||
child.layout(constraints.loosen(), parentUsesSize: true);
|
||||
size = constraints.constrain(Size(shrinkWrapWidth ? child.size.width * (_widthFactor ?? 1.0) : double.infinity,
|
||||
shrinkWrapHeight ? child.size.height * (_heightFactor ?? 1.0) : double.infinity));
|
||||
child!.layout(constraints.loosen(), parentUsesSize: true);
|
||||
size = constraints.constrain(Size(shrinkWrapWidth ? child!.size.width * (_widthFactor ?? 1.0) : double.infinity,
|
||||
shrinkWrapHeight ? child!.size.height * (_heightFactor ?? 1.0) : double.infinity));
|
||||
alignChild();
|
||||
} else {
|
||||
size = constraints.constrain(Size(shrinkWrapWidth ? 0.0 : double.infinity,
|
||||
|
@ -408,14 +406,14 @@ class RenderPositionedBox extends RenderAligningShiftedBox {
|
|||
super.debugPaintSize(context, offset);
|
||||
assert(() {
|
||||
Paint paint;
|
||||
if (child != null && !child.size.isEmpty) {
|
||||
if (child != null && !child!.size.isEmpty) {
|
||||
Path path;
|
||||
paint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 1.0
|
||||
..color = const Color(0xFFFFFF00);
|
||||
path = Path();
|
||||
final BoxParentData childParentData = child.parentData as BoxParentData;
|
||||
final BoxParentData childParentData = child!.parentData as BoxParentData;
|
||||
if (childParentData.offset.dy > 0.0) {
|
||||
// vertical alignment arrows
|
||||
final double headSize = math.min(childParentData.offset.dy * 0.2, 10.0);
|
||||
|
@ -502,13 +500,13 @@ class RenderPositionedBox extends RenderAligningShiftedBox {
|
|||
class RenderConstrainedOverflowBox extends RenderAligningShiftedBox {
|
||||
/// Creates a render object that lets its child overflow itself.
|
||||
RenderConstrainedOverflowBox({
|
||||
RenderBox child,
|
||||
double minWidth,
|
||||
double maxWidth,
|
||||
double minHeight,
|
||||
double maxHeight,
|
||||
RenderBox? child,
|
||||
double? minWidth,
|
||||
double? maxWidth,
|
||||
double? minHeight,
|
||||
double? maxHeight,
|
||||
AlignmentGeometry alignment = Alignment.center,
|
||||
TextDirection textDirection,
|
||||
TextDirection? textDirection,
|
||||
}) : _minWidth = minWidth,
|
||||
_maxWidth = maxWidth,
|
||||
_minHeight = minHeight,
|
||||
|
@ -517,9 +515,9 @@ class RenderConstrainedOverflowBox extends RenderAligningShiftedBox {
|
|||
|
||||
/// The minimum width constraint to give the child. Set this to null (the
|
||||
/// default) to use the constraint from the parent instead.
|
||||
double get minWidth => _minWidth;
|
||||
double _minWidth;
|
||||
set minWidth(double value) {
|
||||
double? get minWidth => _minWidth;
|
||||
double? _minWidth;
|
||||
set minWidth(double? value) {
|
||||
if (_minWidth == value)
|
||||
return;
|
||||
_minWidth = value;
|
||||
|
@ -528,9 +526,9 @@ class RenderConstrainedOverflowBox extends RenderAligningShiftedBox {
|
|||
|
||||
/// The maximum width constraint to give the child. Set this to null (the
|
||||
/// default) to use the constraint from the parent instead.
|
||||
double get maxWidth => _maxWidth;
|
||||
double _maxWidth;
|
||||
set maxWidth(double value) {
|
||||
double? get maxWidth => _maxWidth;
|
||||
double? _maxWidth;
|
||||
set maxWidth(double? value) {
|
||||
if (_maxWidth == value)
|
||||
return;
|
||||
_maxWidth = value;
|
||||
|
@ -539,9 +537,9 @@ class RenderConstrainedOverflowBox extends RenderAligningShiftedBox {
|
|||
|
||||
/// The minimum height constraint to give the child. Set this to null (the
|
||||
/// default) to use the constraint from the parent instead.
|
||||
double get minHeight => _minHeight;
|
||||
double _minHeight;
|
||||
set minHeight(double value) {
|
||||
double? get minHeight => _minHeight;
|
||||
double? _minHeight;
|
||||
set minHeight(double? value) {
|
||||
if (_minHeight == value)
|
||||
return;
|
||||
_minHeight = value;
|
||||
|
@ -550,9 +548,9 @@ class RenderConstrainedOverflowBox extends RenderAligningShiftedBox {
|
|||
|
||||
/// The maximum height constraint to give the child. Set this to null (the
|
||||
/// default) to use the constraint from the parent instead.
|
||||
double get maxHeight => _maxHeight;
|
||||
double _maxHeight;
|
||||
set maxHeight(double value) {
|
||||
double? get maxHeight => _maxHeight;
|
||||
double? _maxHeight;
|
||||
set maxHeight(double? value) {
|
||||
if (_maxHeight == value)
|
||||
return;
|
||||
_maxHeight = value;
|
||||
|
@ -579,7 +577,7 @@ class RenderConstrainedOverflowBox extends RenderAligningShiftedBox {
|
|||
@override
|
||||
void performLayout() {
|
||||
if (child != null) {
|
||||
child.layout(_getInnerConstraints(constraints), parentUsesSize: true);
|
||||
child?.layout(_getInnerConstraints(constraints), parentUsesSize: true);
|
||||
alignChild();
|
||||
}
|
||||
}
|
||||
|
@ -624,10 +622,10 @@ class RenderUnconstrainedBox extends RenderAligningShiftedBox with DebugOverflow
|
|||
///
|
||||
/// The [alignment] must not be null.
|
||||
RenderUnconstrainedBox({
|
||||
@required AlignmentGeometry alignment,
|
||||
@required TextDirection textDirection,
|
||||
Axis constrainedAxis,
|
||||
RenderBox child,
|
||||
required AlignmentGeometry alignment,
|
||||
required TextDirection? textDirection,
|
||||
Axis? constrainedAxis,
|
||||
RenderBox? child,
|
||||
Clip clipBehavior = Clip.none,
|
||||
}) : assert(alignment != null),
|
||||
assert(clipBehavior != null),
|
||||
|
@ -641,9 +639,9 @@ class RenderUnconstrainedBox extends RenderAligningShiftedBox with DebugOverflow
|
|||
/// constraints. If set to [Axis.vertical], then vertical constraints will
|
||||
/// be retained, and if set to [Axis.horizontal], then horizontal constraints
|
||||
/// will be retained.
|
||||
Axis get constrainedAxis => _constrainedAxis;
|
||||
Axis _constrainedAxis;
|
||||
set constrainedAxis(Axis value) {
|
||||
Axis? get constrainedAxis => _constrainedAxis;
|
||||
Axis? _constrainedAxis;
|
||||
set constrainedAxis(Axis? value) {
|
||||
if (_constrainedAxis == value)
|
||||
return;
|
||||
_constrainedAxis = value;
|
||||
|
@ -676,7 +674,7 @@ class RenderUnconstrainedBox extends RenderAligningShiftedBox with DebugOverflow
|
|||
// constrainedAxis is non-null, keep any constraints on that axis.
|
||||
BoxConstraints childConstraints;
|
||||
if (constrainedAxis != null) {
|
||||
switch (constrainedAxis) {
|
||||
switch (constrainedAxis!) {
|
||||
case Axis.horizontal:
|
||||
childConstraints = BoxConstraints(maxWidth: constraints.maxWidth, minWidth: constraints.minWidth);
|
||||
break;
|
||||
|
@ -687,12 +685,12 @@ class RenderUnconstrainedBox extends RenderAligningShiftedBox with DebugOverflow
|
|||
} else {
|
||||
childConstraints = const BoxConstraints();
|
||||
}
|
||||
child.layout(childConstraints, parentUsesSize: true);
|
||||
size = constraints.constrain(child.size);
|
||||
child!.layout(childConstraints, parentUsesSize: true);
|
||||
size = constraints.constrain(child!.size);
|
||||
alignChild();
|
||||
final BoxParentData childParentData = child.parentData as BoxParentData;
|
||||
final BoxParentData childParentData = child!.parentData as BoxParentData;
|
||||
_overflowContainerRect = Offset.zero & size;
|
||||
_overflowChildRect = childParentData.offset & child.size;
|
||||
_overflowChildRect = childParentData.offset & child!.size;
|
||||
} else {
|
||||
size = constraints.smallest;
|
||||
_overflowContainerRect = Rect.zero;
|
||||
|
@ -728,7 +726,7 @@ class RenderUnconstrainedBox extends RenderAligningShiftedBox with DebugOverflow
|
|||
}
|
||||
|
||||
@override
|
||||
Rect describeApproximatePaintClip(RenderObject child) {
|
||||
Rect? describeApproximatePaintClip(RenderObject child) {
|
||||
return _isOverflowing ? Offset.zero & size : null;
|
||||
}
|
||||
|
||||
|
@ -763,10 +761,10 @@ class RenderSizedOverflowBox extends RenderAligningShiftedBox {
|
|||
/// The [textDirection] argument must not be null if the [alignment] is
|
||||
/// direction-sensitive.
|
||||
RenderSizedOverflowBox({
|
||||
RenderBox child,
|
||||
@required Size requestedSize,
|
||||
RenderBox? child,
|
||||
required Size requestedSize,
|
||||
AlignmentGeometry alignment = Alignment.center,
|
||||
TextDirection textDirection,
|
||||
TextDirection? textDirection,
|
||||
}) : assert(requestedSize != null),
|
||||
_requestedSize = requestedSize,
|
||||
super(child: child, alignment: alignment, textDirection: textDirection);
|
||||
|
@ -803,9 +801,9 @@ class RenderSizedOverflowBox extends RenderAligningShiftedBox {
|
|||
}
|
||||
|
||||
@override
|
||||
double computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
double? computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
if (child != null)
|
||||
return child.getDistanceToActualBaseline(baseline);
|
||||
return child!.getDistanceToActualBaseline(baseline);
|
||||
return super.computeDistanceToActualBaseline(baseline);
|
||||
}
|
||||
|
||||
|
@ -813,7 +811,7 @@ class RenderSizedOverflowBox extends RenderAligningShiftedBox {
|
|||
void performLayout() {
|
||||
size = constraints.constrain(_requestedSize);
|
||||
if (child != null) {
|
||||
child.layout(constraints, parentUsesSize: true);
|
||||
child!.layout(constraints, parentUsesSize: true);
|
||||
alignChild();
|
||||
}
|
||||
}
|
||||
|
@ -841,16 +839,16 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
|
|||
/// The [textDirection] must be non-null if the [alignment] is
|
||||
/// direction-sensitive.
|
||||
RenderFractionallySizedOverflowBox({
|
||||
RenderBox child,
|
||||
double widthFactor,
|
||||
double heightFactor,
|
||||
RenderBox? child,
|
||||
double? widthFactor,
|
||||
double? heightFactor,
|
||||
AlignmentGeometry alignment = Alignment.center,
|
||||
TextDirection textDirection,
|
||||
TextDirection? textDirection,
|
||||
}) : _widthFactor = widthFactor,
|
||||
_heightFactor = heightFactor,
|
||||
super(child: child, alignment: alignment, textDirection: textDirection) {
|
||||
assert(_widthFactor == null || _widthFactor >= 0.0);
|
||||
assert(_heightFactor == null || _heightFactor >= 0.0);
|
||||
assert(_widthFactor == null || _widthFactor! >= 0.0);
|
||||
assert(_heightFactor == null || _heightFactor! >= 0.0);
|
||||
}
|
||||
|
||||
/// If non-null, the factor of the incoming width to use.
|
||||
|
@ -858,9 +856,9 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
|
|||
/// If non-null, the child is given a tight width constraint that is the max
|
||||
/// incoming width constraint multiplied by this factor. If null, the child is
|
||||
/// given the incoming width constraints.
|
||||
double get widthFactor => _widthFactor;
|
||||
double _widthFactor;
|
||||
set widthFactor(double value) {
|
||||
double? get widthFactor => _widthFactor;
|
||||
double? _widthFactor;
|
||||
set widthFactor(double? value) {
|
||||
assert(value == null || value >= 0.0);
|
||||
if (_widthFactor == value)
|
||||
return;
|
||||
|
@ -873,9 +871,9 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
|
|||
/// If non-null, the child is given a tight height constraint that is the max
|
||||
/// incoming width constraint multiplied by this factor. If null, the child is
|
||||
/// given the incoming width constraints.
|
||||
double get heightFactor => _heightFactor;
|
||||
double _heightFactor;
|
||||
set heightFactor(double value) {
|
||||
double? get heightFactor => _heightFactor;
|
||||
double? _heightFactor;
|
||||
set heightFactor(double? value) {
|
||||
assert(value == null || value >= 0.0);
|
||||
if (_heightFactor == value)
|
||||
return;
|
||||
|
@ -887,14 +885,14 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
|
|||
double minWidth = constraints.minWidth;
|
||||
double maxWidth = constraints.maxWidth;
|
||||
if (_widthFactor != null) {
|
||||
final double width = maxWidth * _widthFactor;
|
||||
final double width = maxWidth * _widthFactor!;
|
||||
minWidth = width;
|
||||
maxWidth = width;
|
||||
}
|
||||
double minHeight = constraints.minHeight;
|
||||
double maxHeight = constraints.maxHeight;
|
||||
if (_heightFactor != null) {
|
||||
final double height = maxHeight * _heightFactor;
|
||||
final double height = maxHeight * _heightFactor!;
|
||||
minHeight = height;
|
||||
maxHeight = height;
|
||||
}
|
||||
|
@ -912,7 +910,7 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
|
|||
if (child == null) {
|
||||
result = super.computeMinIntrinsicWidth(height);
|
||||
} else { // the following line relies on double.infinity absorption
|
||||
result = child.getMinIntrinsicWidth(height * (_heightFactor ?? 1.0));
|
||||
result = child!.getMinIntrinsicWidth(height * (_heightFactor ?? 1.0));
|
||||
}
|
||||
assert(result.isFinite);
|
||||
return result / (_widthFactor ?? 1.0);
|
||||
|
@ -924,7 +922,7 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
|
|||
if (child == null) {
|
||||
result = super.computeMaxIntrinsicWidth(height);
|
||||
} else { // the following line relies on double.infinity absorption
|
||||
result = child.getMaxIntrinsicWidth(height * (_heightFactor ?? 1.0));
|
||||
result = child!.getMaxIntrinsicWidth(height * (_heightFactor ?? 1.0));
|
||||
}
|
||||
assert(result.isFinite);
|
||||
return result / (_widthFactor ?? 1.0);
|
||||
|
@ -936,7 +934,7 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
|
|||
if (child == null) {
|
||||
result = super.computeMinIntrinsicHeight(width);
|
||||
} else { // the following line relies on double.infinity absorption
|
||||
result = child.getMinIntrinsicHeight(width * (_widthFactor ?? 1.0));
|
||||
result = child!.getMinIntrinsicHeight(width * (_widthFactor ?? 1.0));
|
||||
}
|
||||
assert(result.isFinite);
|
||||
return result / (_heightFactor ?? 1.0);
|
||||
|
@ -948,7 +946,7 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
|
|||
if (child == null) {
|
||||
result = super.computeMaxIntrinsicHeight(width);
|
||||
} else { // the following line relies on double.infinity absorption
|
||||
result = child.getMaxIntrinsicHeight(width * (_widthFactor ?? 1.0));
|
||||
result = child!.getMaxIntrinsicHeight(width * (_widthFactor ?? 1.0));
|
||||
}
|
||||
assert(result.isFinite);
|
||||
return result / (_heightFactor ?? 1.0);
|
||||
|
@ -957,8 +955,8 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
|
|||
@override
|
||||
void performLayout() {
|
||||
if (child != null) {
|
||||
child.layout(_getInnerConstraints(constraints), parentUsesSize: true);
|
||||
size = constraints.constrain(child.size);
|
||||
child!.layout(_getInnerConstraints(constraints), parentUsesSize: true);
|
||||
size = constraints.constrain(child!.size);
|
||||
alignChild();
|
||||
} else {
|
||||
size = constraints.constrain(_getInnerConstraints(constraints).constrain(Size.zero));
|
||||
|
@ -1003,9 +1001,9 @@ abstract class SingleChildLayoutDelegate {
|
|||
/// Creates a layout delegate.
|
||||
///
|
||||
/// The layout will update whenever [relayout] notifies its listeners.
|
||||
const SingleChildLayoutDelegate({ Listenable relayout }) : _relayout = relayout;
|
||||
const SingleChildLayoutDelegate({ Listenable? relayout }) : _relayout = relayout;
|
||||
|
||||
final Listenable _relayout;
|
||||
final Listenable? _relayout;
|
||||
|
||||
/// The size of this object given the incoming constraints.
|
||||
///
|
||||
|
@ -1065,8 +1063,8 @@ class RenderCustomSingleChildLayoutBox extends RenderShiftedBox {
|
|||
///
|
||||
/// The [delegate] argument must not be null.
|
||||
RenderCustomSingleChildLayoutBox({
|
||||
RenderBox child,
|
||||
@required SingleChildLayoutDelegate delegate,
|
||||
RenderBox? child,
|
||||
required SingleChildLayoutDelegate delegate,
|
||||
}) : assert(delegate != null),
|
||||
_delegate = delegate,
|
||||
super(child);
|
||||
|
@ -1083,20 +1081,20 @@ class RenderCustomSingleChildLayoutBox extends RenderShiftedBox {
|
|||
markNeedsLayout();
|
||||
_delegate = newDelegate;
|
||||
if (attached) {
|
||||
oldDelegate?._relayout?.removeListener(markNeedsLayout);
|
||||
newDelegate?._relayout?.addListener(markNeedsLayout);
|
||||
oldDelegate._relayout?.removeListener(markNeedsLayout);
|
||||
newDelegate._relayout?.addListener(markNeedsLayout);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void attach(PipelineOwner owner) {
|
||||
super.attach(owner);
|
||||
_delegate?._relayout?.addListener(markNeedsLayout);
|
||||
_delegate._relayout?.addListener(markNeedsLayout);
|
||||
}
|
||||
|
||||
@override
|
||||
void detach() {
|
||||
_delegate?._relayout?.removeListener(markNeedsLayout);
|
||||
_delegate._relayout?.removeListener(markNeedsLayout);
|
||||
super.detach();
|
||||
}
|
||||
|
||||
|
@ -1146,9 +1144,9 @@ class RenderCustomSingleChildLayoutBox extends RenderShiftedBox {
|
|||
if (child != null) {
|
||||
final BoxConstraints childConstraints = delegate.getConstraintsForChild(constraints);
|
||||
assert(childConstraints.debugAssertIsValid(isAppliedConstraint: true));
|
||||
child.layout(childConstraints, parentUsesSize: !childConstraints.isTight);
|
||||
final BoxParentData childParentData = child.parentData as BoxParentData;
|
||||
childParentData.offset = delegate.getPositionForChild(size, childConstraints.isTight ? childConstraints.smallest : child.size);
|
||||
child!.layout(childConstraints, parentUsesSize: !childConstraints.isTight);
|
||||
final BoxParentData childParentData = child!.parentData as BoxParentData;
|
||||
childParentData.offset = delegate.getPositionForChild(size, childConstraints.isTight ? childConstraints.smallest : child!.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1174,9 +1172,9 @@ class RenderBaseline extends RenderShiftedBox {
|
|||
///
|
||||
/// The [baseline] and [baselineType] arguments must not be null.
|
||||
RenderBaseline({
|
||||
RenderBox child,
|
||||
@required double baseline,
|
||||
@required TextBaseline baselineType,
|
||||
RenderBox? child,
|
||||
required double baseline,
|
||||
required TextBaseline baselineType,
|
||||
}) : assert(baseline != null),
|
||||
assert(baselineType != null),
|
||||
_baseline = baseline,
|
||||
|
@ -1210,13 +1208,13 @@ class RenderBaseline extends RenderShiftedBox {
|
|||
void performLayout() {
|
||||
if (child != null) {
|
||||
final BoxConstraints constraints = this.constraints;
|
||||
child.layout(constraints.loosen(), parentUsesSize: true);
|
||||
final double childBaseline = child.getDistanceToBaseline(baselineType);
|
||||
child!.layout(constraints.loosen(), parentUsesSize: true);
|
||||
final double childBaseline = child!.getDistanceToBaseline(baselineType)!;
|
||||
final double actualBaseline = baseline;
|
||||
final double top = actualBaseline - childBaseline;
|
||||
final BoxParentData childParentData = child.parentData as BoxParentData;
|
||||
final BoxParentData childParentData = child!.parentData as BoxParentData;
|
||||
childParentData.offset = Offset(0.0, top);
|
||||
final Size childSize = child.size;
|
||||
final Size childSize = child!.size;
|
||||
size = constraints.constrain(Size(childSize.width, top + childSize.height));
|
||||
} else {
|
||||
performResize();
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -61,7 +59,6 @@ AxisDirection applyGrowthDirectionToAxisDirection(AxisDirection axisDirection, G
|
|||
case GrowthDirection.reverse:
|
||||
return flipAxisDirection(axisDirection);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Flips the [ScrollDirection] if the [GrowthDirection] is [GrowthDirection.reverse].
|
||||
|
@ -82,7 +79,6 @@ ScrollDirection applyGrowthDirectionToScrollDirection(ScrollDirection scrollDire
|
|||
case GrowthDirection.reverse:
|
||||
return flipScrollDirection(scrollDirection);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Immutable layout constraints for [RenderSliver] layout.
|
||||
|
@ -97,18 +93,18 @@ class SliverConstraints extends Constraints {
|
|||
///
|
||||
/// All of the argument must not be null.
|
||||
const SliverConstraints({
|
||||
@required this.axisDirection,
|
||||
@required this.growthDirection,
|
||||
@required this.userScrollDirection,
|
||||
@required this.scrollOffset,
|
||||
@required this.precedingScrollExtent,
|
||||
@required this.overlap,
|
||||
@required this.remainingPaintExtent,
|
||||
@required this.crossAxisExtent,
|
||||
@required this.crossAxisDirection,
|
||||
@required this.viewportMainAxisExtent,
|
||||
@required this.remainingCacheExtent,
|
||||
@required this.cacheOrigin,
|
||||
required this.axisDirection,
|
||||
required this.growthDirection,
|
||||
required this.userScrollDirection,
|
||||
required this.scrollOffset,
|
||||
required this.precedingScrollExtent,
|
||||
required this.overlap,
|
||||
required this.remainingPaintExtent,
|
||||
required this.crossAxisExtent,
|
||||
required this.crossAxisDirection,
|
||||
required this.viewportMainAxisExtent,
|
||||
required this.remainingCacheExtent,
|
||||
required this.cacheOrigin,
|
||||
}) : assert(axisDirection != null),
|
||||
assert(growthDirection != null),
|
||||
assert(userScrollDirection != null),
|
||||
|
@ -125,18 +121,18 @@ class SliverConstraints extends Constraints {
|
|||
/// Creates a copy of this object but with the given fields replaced with the
|
||||
/// new values.
|
||||
SliverConstraints copyWith({
|
||||
AxisDirection axisDirection,
|
||||
GrowthDirection growthDirection,
|
||||
ScrollDirection userScrollDirection,
|
||||
double scrollOffset,
|
||||
double precedingScrollExtent,
|
||||
double overlap,
|
||||
double remainingPaintExtent,
|
||||
double crossAxisExtent,
|
||||
AxisDirection crossAxisDirection,
|
||||
double viewportMainAxisExtent,
|
||||
double remainingCacheExtent,
|
||||
double cacheOrigin,
|
||||
AxisDirection? axisDirection,
|
||||
GrowthDirection? growthDirection,
|
||||
ScrollDirection? userScrollDirection,
|
||||
double? scrollOffset,
|
||||
double? precedingScrollExtent,
|
||||
double? overlap,
|
||||
double? remainingPaintExtent,
|
||||
double? crossAxisExtent,
|
||||
AxisDirection? crossAxisDirection,
|
||||
double? viewportMainAxisExtent,
|
||||
double? remainingCacheExtent,
|
||||
double? cacheOrigin,
|
||||
}) {
|
||||
return SliverConstraints(
|
||||
axisDirection: axisDirection ?? this.axisDirection,
|
||||
|
@ -360,9 +356,7 @@ class SliverConstraints extends Constraints {
|
|||
case GrowthDirection.reverse:
|
||||
return GrowthDirection.forward;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -388,7 +382,7 @@ class SliverConstraints extends Constraints {
|
|||
BoxConstraints asBoxConstraints({
|
||||
double minExtent = 0.0,
|
||||
double maxExtent = double.infinity,
|
||||
double crossAxisExtent,
|
||||
double? crossAxisExtent,
|
||||
}) {
|
||||
crossAxisExtent ??= this.crossAxisExtent;
|
||||
switch (axis) {
|
||||
|
@ -407,13 +401,12 @@ class SliverConstraints extends Constraints {
|
|||
maxHeight: maxExtent,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
bool debugAssertIsValid({
|
||||
bool isAppliedConstraint = false,
|
||||
InformationCollector informationCollector,
|
||||
InformationCollector? informationCollector,
|
||||
}) {
|
||||
assert(() {
|
||||
bool hasErrors = false;
|
||||
|
@ -540,14 +533,14 @@ class SliverGeometry with Diagnosticable {
|
|||
this.scrollExtent = 0.0,
|
||||
this.paintExtent = 0.0,
|
||||
this.paintOrigin = 0.0,
|
||||
double layoutExtent,
|
||||
double? layoutExtent,
|
||||
this.maxPaintExtent = 0.0,
|
||||
this.maxScrollObstructionExtent = 0.0,
|
||||
double hitTestExtent,
|
||||
bool visible,
|
||||
double? hitTestExtent,
|
||||
bool? visible,
|
||||
this.hasVisualOverflow = false,
|
||||
this.scrollOffsetCorrection,
|
||||
double cacheExtent,
|
||||
double? cacheExtent,
|
||||
}) : assert(scrollExtent != null),
|
||||
assert(paintExtent != null),
|
||||
assert(paintOrigin != null),
|
||||
|
@ -692,7 +685,7 @@ class SliverGeometry with Diagnosticable {
|
|||
/// If the parent is also a [RenderSliver], it must propagate this value
|
||||
/// in its own [RenderSliver.geometry] property until a viewport which adjusts
|
||||
/// its offset based on this value.
|
||||
final double scrollOffsetCorrection;
|
||||
final double? scrollOffsetCorrection;
|
||||
|
||||
/// How many pixels the sliver has consumed in the
|
||||
/// [SliverConstraints.remainingCacheExtent].
|
||||
|
@ -711,10 +704,10 @@ class SliverGeometry with Diagnosticable {
|
|||
///
|
||||
/// Does nothing if asserts are disabled. Always returns true.
|
||||
bool debugAssertIsValid({
|
||||
InformationCollector informationCollector,
|
||||
InformationCollector? informationCollector,
|
||||
}) {
|
||||
assert(() {
|
||||
void verify(bool check, String summary, {List<DiagnosticsNode> details}) {
|
||||
void verify(bool check, String summary, {List<DiagnosticsNode>? details}) {
|
||||
if (check)
|
||||
return;
|
||||
throw FlutterError.fromParts(<DiagnosticsNode>[
|
||||
|
@ -797,7 +790,7 @@ class SliverGeometry with Diagnosticable {
|
|||
///
|
||||
/// * [RenderSliver.hitTest], which documents more details around hit testing
|
||||
/// [RenderSliver]s.
|
||||
typedef SliverHitTest = bool Function(SliverHitTestResult result, { @required double mainAxisPosition, @required double crossAxisPosition });
|
||||
typedef SliverHitTest = bool Function(SliverHitTestResult result, { required double mainAxisPosition, required double crossAxisPosition });
|
||||
|
||||
/// The result of performing a hit test on [RenderSliver]s.
|
||||
///
|
||||
|
@ -848,12 +841,12 @@ class SliverHitTestResult extends HitTestResult {
|
|||
///
|
||||
/// The function returns the return value of `hitTest`.
|
||||
bool addWithAxisOffset({
|
||||
@required Offset paintOffset,
|
||||
@required double mainAxisOffset,
|
||||
@required double crossAxisOffset,
|
||||
@required double mainAxisPosition,
|
||||
@required double crossAxisPosition,
|
||||
@required SliverHitTest hitTest,
|
||||
required Offset? paintOffset,
|
||||
required double mainAxisOffset,
|
||||
required double crossAxisOffset,
|
||||
required double mainAxisPosition,
|
||||
required double crossAxisPosition,
|
||||
required SliverHitTest hitTest,
|
||||
}) {
|
||||
assert(mainAxisOffset != null);
|
||||
assert(crossAxisOffset != null);
|
||||
|
@ -885,8 +878,8 @@ class SliverHitTestEntry extends HitTestEntry {
|
|||
/// The [mainAxisPosition] and [crossAxisPosition] arguments must not be null.
|
||||
SliverHitTestEntry(
|
||||
RenderSliver target, {
|
||||
@required this.mainAxisPosition,
|
||||
@required this.crossAxisPosition,
|
||||
required this.mainAxisPosition,
|
||||
required this.crossAxisPosition,
|
||||
}) : assert(mainAxisPosition != null),
|
||||
assert(crossAxisPosition != null),
|
||||
super(target);
|
||||
|
@ -936,10 +929,10 @@ class SliverLogicalParentData extends ParentData {
|
|||
/// In a typical list, this does not change as the parent is scrolled.
|
||||
///
|
||||
/// Defaults to null.
|
||||
double layoutOffset;
|
||||
double? layoutOffset;
|
||||
|
||||
@override
|
||||
String toString() => 'layoutOffset=${layoutOffset == null ? 'None': layoutOffset.toStringAsFixed(1)}';
|
||||
String toString() => 'layoutOffset=${layoutOffset == null ? 'None': layoutOffset!.toStringAsFixed(1)}';
|
||||
}
|
||||
|
||||
/// Parent data for slivers that have multiple children and that position their
|
||||
|
@ -967,6 +960,7 @@ class SliverPhysicalParentData extends ParentData {
|
|||
/// Used to implement [RenderObject.applyPaintTransform] by slivers that use
|
||||
/// [SliverPhysicalParentData].
|
||||
void applyPaintTransform(Matrix4 transform) {
|
||||
// Hit test logic relies on this always providing an invertible matrix.
|
||||
transform.translate(paintOffset.dx, paintOffset.dy);
|
||||
}
|
||||
|
||||
|
@ -1147,9 +1141,9 @@ abstract class RenderSliver extends RenderObject {
|
|||
/// [performLayout] or [performResize] functions. If you wish to change the
|
||||
/// geometry of a sliver outside of those functions, call [markNeedsLayout]
|
||||
/// instead to schedule a layout of the sliver.
|
||||
SliverGeometry get geometry => _geometry;
|
||||
SliverGeometry _geometry;
|
||||
set geometry(SliverGeometry value) {
|
||||
SliverGeometry? get geometry => _geometry;
|
||||
SliverGeometry? _geometry;
|
||||
set geometry(SliverGeometry? value) {
|
||||
assert(!(debugDoingThisResize && debugDoingThisLayout));
|
||||
assert(sizedByParent || !debugDoingThisResize);
|
||||
assert(() {
|
||||
|
@ -1157,13 +1151,13 @@ abstract class RenderSliver extends RenderObject {
|
|||
(!sizedByParent && debugDoingThisLayout))
|
||||
return true;
|
||||
assert(!debugDoingThisResize);
|
||||
DiagnosticsNode contract, violation, hint;
|
||||
DiagnosticsNode? contract, violation, hint;
|
||||
if (debugDoingThisLayout) {
|
||||
assert(sizedByParent);
|
||||
violation = ErrorDescription('It appears that the geometry setter was called from performLayout().');
|
||||
} else {
|
||||
violation = ErrorDescription('The geometry setter was called from outside layout (neither performResize() nor performLayout() were being run for this object).');
|
||||
if (owner != null && owner.debugDoingLayout)
|
||||
if (owner != null && owner!.debugDoingLayout)
|
||||
hint = ErrorDescription('Only the object itself can set its geometry. It is a contract violation for other objects to set it.');
|
||||
}
|
||||
if (sizedByParent)
|
||||
|
@ -1193,17 +1187,16 @@ abstract class RenderSliver extends RenderObject {
|
|||
case Axis.horizontal:
|
||||
return Rect.fromLTWH(
|
||||
0.0, 0.0,
|
||||
geometry.paintExtent,
|
||||
geometry!.paintExtent,
|
||||
constraints.crossAxisExtent,
|
||||
);
|
||||
case Axis.vertical:
|
||||
return Rect.fromLTWH(
|
||||
0.0, 0.0,
|
||||
constraints.crossAxisExtent,
|
||||
geometry.paintExtent,
|
||||
geometry!.paintExtent,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -1211,19 +1204,19 @@ abstract class RenderSliver extends RenderObject {
|
|||
|
||||
@override
|
||||
void debugAssertDoesMeetConstraints() {
|
||||
assert(geometry.debugAssertIsValid(
|
||||
assert(geometry!.debugAssertIsValid(
|
||||
informationCollector: () sync* {
|
||||
yield describeForError('The RenderSliver that returned the offending geometry was');
|
||||
}
|
||||
));
|
||||
assert(() {
|
||||
if (geometry.paintOrigin + geometry.paintExtent > constraints.remainingPaintExtent) {
|
||||
if (geometry!.paintOrigin + geometry!.paintExtent > constraints.remainingPaintExtent) {
|
||||
throw FlutterError.fromParts(<DiagnosticsNode>[
|
||||
ErrorSummary('SliverGeometry has a paintOffset that exceeds the remainingPaintExtent from the constraints.'),
|
||||
describeForError('The render object whose geometry violates the constraints is the following'),
|
||||
..._debugCompareFloats(
|
||||
'remainingPaintExtent', constraints.remainingPaintExtent,
|
||||
'paintOrigin + paintExtent', geometry.paintOrigin + geometry.paintExtent,
|
||||
'paintOrigin + paintExtent', geometry!.paintOrigin + geometry!.paintExtent,
|
||||
),
|
||||
ErrorDescription(
|
||||
'The paintOrigin and paintExtent must cause the child sliver to paint '
|
||||
|
@ -1290,8 +1283,8 @@ abstract class RenderSliver extends RenderObject {
|
|||
/// The most straight-forward way to implement hit testing for a new sliver
|
||||
/// render object is to override its [hitTestSelf] and [hitTestChildren]
|
||||
/// methods.
|
||||
bool hitTest(SliverHitTestResult result, { @required double mainAxisPosition, @required double crossAxisPosition }) {
|
||||
if (mainAxisPosition >= 0.0 && mainAxisPosition < geometry.hitTestExtent &&
|
||||
bool hitTest(SliverHitTestResult result, { required double mainAxisPosition, required double crossAxisPosition }) {
|
||||
if (mainAxisPosition >= 0.0 && mainAxisPosition < geometry!.hitTestExtent &&
|
||||
crossAxisPosition >= 0.0 && crossAxisPosition < constraints.crossAxisExtent) {
|
||||
if (hitTestChildren(result, mainAxisPosition: mainAxisPosition, crossAxisPosition: crossAxisPosition) ||
|
||||
hitTestSelf(mainAxisPosition: mainAxisPosition, crossAxisPosition: crossAxisPosition)) {
|
||||
|
@ -1314,7 +1307,7 @@ abstract class RenderSliver extends RenderObject {
|
|||
///
|
||||
/// For a discussion of the semantics of the arguments, see [hitTest].
|
||||
@protected
|
||||
bool hitTestSelf({ @required double mainAxisPosition, @required double crossAxisPosition }) => false;
|
||||
bool hitTestSelf({ required double mainAxisPosition, required double crossAxisPosition }) => false;
|
||||
|
||||
/// Override this method to check whether any children are located at the
|
||||
/// given position.
|
||||
|
@ -1328,7 +1321,7 @@ abstract class RenderSliver extends RenderObject {
|
|||
///
|
||||
/// For a discussion of the semantics of the arguments, see [hitTest].
|
||||
@protected
|
||||
bool hitTestChildren(SliverHitTestResult result, { @required double mainAxisPosition, @required double crossAxisPosition }) => false;
|
||||
bool hitTestChildren(SliverHitTestResult result, { required double mainAxisPosition, required double crossAxisPosition }) => false;
|
||||
|
||||
/// Computes the portion of the region from `from` to `to` that is visible,
|
||||
/// assuming that only the region from the [SliverConstraints.scrollOffset]
|
||||
|
@ -1347,12 +1340,12 @@ abstract class RenderSliver extends RenderObject {
|
|||
/// function's results will not be consistent.
|
||||
// This could be a static method but isn't, because it would be less convenient
|
||||
// to call it from subclasses if it was.
|
||||
double calculatePaintOffset(SliverConstraints constraints, { @required double from, @required double to }) {
|
||||
double calculatePaintOffset(SliverConstraints constraints, { required double from, required double to }) {
|
||||
assert(from <= to);
|
||||
final double a = constraints.scrollOffset;
|
||||
final double b = constraints.scrollOffset + constraints.remainingPaintExtent;
|
||||
// the clamp on the next line is to avoid floating point rounding errors
|
||||
return (to.clamp(a, b) - from.clamp(a, b)).clamp(0.0, constraints.remainingPaintExtent) as double;
|
||||
return (to.clamp(a, b) - from.clamp(a, b)).clamp(0.0, constraints.remainingPaintExtent);
|
||||
}
|
||||
|
||||
/// Computes the portion of the region from `from` to `to` that is within
|
||||
|
@ -1363,12 +1356,12 @@ abstract class RenderSliver extends RenderObject {
|
|||
///
|
||||
/// This method is not useful if there is not a 1:1 relationship between
|
||||
/// consumed scroll offset and consumed cache extent.
|
||||
double calculateCacheOffset(SliverConstraints constraints, { @required double from, @required double to }) {
|
||||
double calculateCacheOffset(SliverConstraints constraints, { required double from, required double to }) {
|
||||
assert(from <= to);
|
||||
final double a = constraints.scrollOffset + constraints.cacheOrigin;
|
||||
final double b = constraints.scrollOffset + constraints.remainingCacheExtent;
|
||||
// the clamp on the next line is to avoid floating point rounding errors
|
||||
return (to.clamp(a, b) - from.clamp(a, b)).clamp(0.0, constraints.remainingCacheExtent) as double;
|
||||
return (to.clamp(a, b) - from.clamp(a, b)).clamp(0.0, constraints.remainingCacheExtent);
|
||||
}
|
||||
|
||||
/// Returns the distance from the leading _visible_ edge of the sliver to the
|
||||
|
@ -1429,7 +1422,7 @@ abstract class RenderSliver extends RenderObject {
|
|||
/// [childMainAxisPosition] gives the distance from the leading _visible_ edge
|
||||
/// of the sliver whereas [childScrollOffset] gives the distance from sliver's
|
||||
/// zero scroll offset.
|
||||
double childScrollOffset(covariant RenderObject child) {
|
||||
double? childScrollOffset(covariant RenderObject child) {
|
||||
assert(child.parent == this);
|
||||
return 0.0;
|
||||
}
|
||||
|
@ -1456,15 +1449,14 @@ abstract class RenderSliver extends RenderObject {
|
|||
assert(!debugNeedsLayout);
|
||||
switch (applyGrowthDirectionToAxisDirection(constraints.axisDirection, constraints.growthDirection)) {
|
||||
case AxisDirection.up:
|
||||
return Size(constraints.crossAxisExtent, -geometry.paintExtent);
|
||||
return Size(constraints.crossAxisExtent, -geometry!.paintExtent);
|
||||
case AxisDirection.right:
|
||||
return Size(geometry.paintExtent, constraints.crossAxisExtent);
|
||||
return Size(geometry!.paintExtent, constraints.crossAxisExtent);
|
||||
case AxisDirection.down:
|
||||
return Size(constraints.crossAxisExtent, geometry.paintExtent);
|
||||
return Size(constraints.crossAxisExtent, geometry!.paintExtent);
|
||||
case AxisDirection.left:
|
||||
return Size(-geometry.paintExtent, constraints.crossAxisExtent);
|
||||
return Size(-geometry!.paintExtent, constraints.crossAxisExtent);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// This returns the absolute [Size] of the sliver.
|
||||
|
@ -1483,12 +1475,11 @@ abstract class RenderSliver extends RenderObject {
|
|||
switch (constraints.axisDirection) {
|
||||
case AxisDirection.up:
|
||||
case AxisDirection.down:
|
||||
return Size(constraints.crossAxisExtent, geometry.paintExtent);
|
||||
return Size(constraints.crossAxisExtent, geometry!.paintExtent);
|
||||
case AxisDirection.right:
|
||||
case AxisDirection.left:
|
||||
return Size(geometry.paintExtent, constraints.crossAxisExtent);
|
||||
return Size(geometry!.paintExtent, constraints.crossAxisExtent);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void _debugDrawArrow(Canvas canvas, Paint paint, Offset p0, Offset p1, GrowthDirection direction) {
|
||||
|
@ -1532,13 +1523,13 @@ abstract class RenderSliver extends RenderObject {
|
|||
void debugPaint(PaintingContext context, Offset offset) {
|
||||
assert(() {
|
||||
if (debugPaintSizeEnabled) {
|
||||
final double strokeWidth = math.min(4.0, geometry.paintExtent / 30.0);
|
||||
final double strokeWidth = math.min(4.0, geometry!.paintExtent / 30.0);
|
||||
final Paint paint = Paint()
|
||||
..color = const Color(0xFF33CC33)
|
||||
..strokeWidth = strokeWidth
|
||||
..style = PaintingStyle.stroke
|
||||
..maskFilter = MaskFilter.blur(BlurStyle.solid, strokeWidth);
|
||||
final double arrowExtent = geometry.paintExtent;
|
||||
final double arrowExtent = geometry!.paintExtent;
|
||||
final double padding = math.max(2.0, strokeWidth);
|
||||
final Canvas canvas = context.canvas;
|
||||
canvas.drawCircle(
|
||||
|
@ -1646,7 +1637,7 @@ abstract class RenderSliverHelpers implements RenderSliver {
|
|||
///
|
||||
/// Calling this for a child that is not visible is not valid.
|
||||
@protected
|
||||
bool hitTestBoxChild(BoxHitTestResult result, RenderBox child, { @required double mainAxisPosition, @required double crossAxisPosition }) {
|
||||
bool hitTestBoxChild(BoxHitTestResult result, RenderBox child, { required double mainAxisPosition, required double crossAxisPosition }) {
|
||||
final bool rightWayUp = _getRightWayUp(constraints);
|
||||
double delta = childMainAxisPosition(child);
|
||||
final double crossAxisDelta = childCrossAxisPosition(child);
|
||||
|
@ -1658,7 +1649,7 @@ abstract class RenderSliverHelpers implements RenderSliver {
|
|||
case Axis.horizontal:
|
||||
if (!rightWayUp) {
|
||||
absolutePosition = child.size.width - absolutePosition;
|
||||
delta = geometry.paintExtent - child.size.width - delta;
|
||||
delta = geometry!.paintExtent - child.size.width - delta;
|
||||
}
|
||||
paintOffset = Offset(delta, crossAxisDelta);
|
||||
transformedPosition = Offset(absolutePosition, absoluteCrossAxisPosition);
|
||||
|
@ -1666,7 +1657,7 @@ abstract class RenderSliverHelpers implements RenderSliver {
|
|||
case Axis.vertical:
|
||||
if (!rightWayUp) {
|
||||
absolutePosition = child.size.height - absolutePosition;
|
||||
delta = geometry.paintExtent - child.size.height - delta;
|
||||
delta = geometry!.paintExtent - child.size.height - delta;
|
||||
}
|
||||
paintOffset = Offset(crossAxisDelta, delta);
|
||||
transformedPosition = Offset(absoluteCrossAxisPosition, absolutePosition);
|
||||
|
@ -1674,10 +1665,9 @@ abstract class RenderSliverHelpers implements RenderSliver {
|
|||
}
|
||||
assert(paintOffset != null);
|
||||
assert(transformedPosition != null);
|
||||
return result.addWithPaintOffset(
|
||||
offset: paintOffset,
|
||||
position: null, // Manually adapting from sliver to box position above.
|
||||
hitTest: (BoxHitTestResult result, Offset _) {
|
||||
return result.addWithOutOfBandPosition(
|
||||
paintOffset: paintOffset,
|
||||
hitTest: (BoxHitTestResult result) {
|
||||
return child.hitTest(result, position: transformedPosition);
|
||||
},
|
||||
);
|
||||
|
@ -1700,12 +1690,12 @@ abstract class RenderSliverHelpers implements RenderSliver {
|
|||
switch (constraints.axis) {
|
||||
case Axis.horizontal:
|
||||
if (!rightWayUp)
|
||||
delta = geometry.paintExtent - child.size.width - delta;
|
||||
delta = geometry!.paintExtent - child.size.width - delta;
|
||||
transform.translate(delta, crossAxisDelta);
|
||||
break;
|
||||
case Axis.vertical:
|
||||
if (!rightWayUp)
|
||||
delta = geometry.paintExtent - child.size.height - delta;
|
||||
delta = geometry!.paintExtent - child.size.height - delta;
|
||||
transform.translate(crossAxisDelta, delta);
|
||||
break;
|
||||
}
|
||||
|
@ -1728,7 +1718,7 @@ abstract class RenderSliverHelpers implements RenderSliver {
|
|||
abstract class RenderSliverSingleBoxAdapter extends RenderSliver with RenderObjectWithChildMixin<RenderBox>, RenderSliverHelpers {
|
||||
/// Creates a [RenderSliver] that wraps a [RenderBox].
|
||||
RenderSliverSingleBoxAdapter({
|
||||
RenderBox child,
|
||||
RenderBox? child,
|
||||
}) {
|
||||
this.child = child;
|
||||
}
|
||||
|
@ -1765,10 +1755,10 @@ abstract class RenderSliverSingleBoxAdapter extends RenderSliver with RenderObje
|
|||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(SliverHitTestResult result, { @required double mainAxisPosition, @required double crossAxisPosition }) {
|
||||
assert(geometry.hitTestExtent > 0.0);
|
||||
bool hitTestChildren(SliverHitTestResult result, { required double mainAxisPosition, required double crossAxisPosition }) {
|
||||
assert(geometry!.hitTestExtent > 0.0);
|
||||
if (child != null)
|
||||
return hitTestBoxChild(BoxHitTestResult.wrap(result), child, mainAxisPosition: mainAxisPosition, crossAxisPosition: crossAxisPosition);
|
||||
return hitTestBoxChild(BoxHitTestResult.wrap(result), child!, mainAxisPosition: mainAxisPosition, crossAxisPosition: crossAxisPosition);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1787,9 +1777,9 @@ abstract class RenderSliverSingleBoxAdapter extends RenderSliver with RenderObje
|
|||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
if (child != null && geometry.visible) {
|
||||
final SliverPhysicalParentData childParentData = child.parentData as SliverPhysicalParentData;
|
||||
context.paintChild(child, offset + childParentData.paintOffset);
|
||||
if (child != null && geometry!.visible) {
|
||||
final SliverPhysicalParentData childParentData = child!.parentData as SliverPhysicalParentData;
|
||||
context.paintChild(child!, offset + childParentData.paintOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1809,7 +1799,7 @@ abstract class RenderSliverSingleBoxAdapter extends RenderSliver with RenderObje
|
|||
class RenderSliverToBoxAdapter extends RenderSliverSingleBoxAdapter {
|
||||
/// Creates a [RenderSliver] that wraps a [RenderBox].
|
||||
RenderSliverToBoxAdapter({
|
||||
RenderBox child,
|
||||
RenderBox? child,
|
||||
}) : super(child: child);
|
||||
|
||||
@override
|
||||
|
@ -1819,14 +1809,14 @@ class RenderSliverToBoxAdapter extends RenderSliverSingleBoxAdapter {
|
|||
return;
|
||||
}
|
||||
final SliverConstraints constraints = this.constraints;
|
||||
child.layout(constraints.asBoxConstraints(), parentUsesSize: true);
|
||||
child!.layout(constraints.asBoxConstraints(), parentUsesSize: true);
|
||||
double childExtent;
|
||||
switch (constraints.axis) {
|
||||
case Axis.horizontal:
|
||||
childExtent = child.size.width;
|
||||
childExtent = child!.size.width;
|
||||
break;
|
||||
case Axis.vertical:
|
||||
childExtent = child.size.height;
|
||||
childExtent = child!.size.height;
|
||||
break;
|
||||
}
|
||||
assert(childExtent != null);
|
||||
|
@ -1843,6 +1833,6 @@ class RenderSliverToBoxAdapter extends RenderSliverSingleBoxAdapter {
|
|||
hitTestExtent: paintedChildSize,
|
||||
hasVisualOverflow: childExtent > constraints.remainingPaintExtent || constraints.scrollOffset > 0.0,
|
||||
);
|
||||
setChildParentData(child, constraints, geometry);
|
||||
setChildParentData(child!, constraints, geometry!);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'box.dart';
|
||||
import 'object.dart';
|
||||
import 'sliver.dart';
|
||||
|
@ -35,7 +31,7 @@ class RenderSliverFillViewport extends RenderSliverFixedExtentBoxAdaptor {
|
|||
///
|
||||
/// The [childManager] argument must not be null.
|
||||
RenderSliverFillViewport({
|
||||
@required RenderSliverBoxChildManager childManager,
|
||||
required RenderSliverBoxChildManager childManager,
|
||||
double viewportFraction = 1.0,
|
||||
}) : assert(viewportFraction != null),
|
||||
assert(viewportFraction > 0.0),
|
||||
|
@ -85,7 +81,7 @@ class RenderSliverFillViewport extends RenderSliverFixedExtentBoxAdaptor {
|
|||
class RenderSliverFillRemainingWithScrollable extends RenderSliverSingleBoxAdapter {
|
||||
/// Creates a [RenderSliver] that wraps a scrollable [RenderBox] which is
|
||||
/// sized to fit the remaining space in the viewport.
|
||||
RenderSliverFillRemainingWithScrollable({ RenderBox child }) : super(child: child);
|
||||
RenderSliverFillRemainingWithScrollable({ RenderBox? child }) : super(child: child);
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
|
@ -94,7 +90,7 @@ class RenderSliverFillRemainingWithScrollable extends RenderSliverSingleBoxAdapt
|
|||
final double extent = constraints.remainingPaintExtent - math.min(constraints.overlap, 0.0);
|
||||
|
||||
if (child != null)
|
||||
child.layout(constraints.asBoxConstraints(
|
||||
child!.layout(constraints.asBoxConstraints(
|
||||
minExtent: extent,
|
||||
maxExtent: extent,
|
||||
));
|
||||
|
@ -109,7 +105,7 @@ class RenderSliverFillRemainingWithScrollable extends RenderSliverSingleBoxAdapt
|
|||
hasVisualOverflow: extent > constraints.remainingPaintExtent || constraints.scrollOffset > 0.0,
|
||||
);
|
||||
if (child != null)
|
||||
setChildParentData(child, constraints, geometry);
|
||||
setChildParentData(child!, constraints, geometry!);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,7 +132,7 @@ class RenderSliverFillRemainingWithScrollable extends RenderSliverSingleBoxAdapt
|
|||
class RenderSliverFillRemaining extends RenderSliverSingleBoxAdapter {
|
||||
/// Creates a [RenderSliver] that wraps a non-scrollable [RenderBox] which is
|
||||
/// sized to fit the remaining space in the viewport.
|
||||
RenderSliverFillRemaining({ RenderBox child }) : super(child: child);
|
||||
RenderSliverFillRemaining({ RenderBox? child }) : super(child: child);
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
|
@ -149,10 +145,10 @@ class RenderSliverFillRemaining extends RenderSliverSingleBoxAdapter {
|
|||
double childExtent;
|
||||
switch (constraints.axis) {
|
||||
case Axis.horizontal:
|
||||
childExtent = child.getMaxIntrinsicWidth(constraints.crossAxisExtent);
|
||||
childExtent = child!.getMaxIntrinsicWidth(constraints.crossAxisExtent);
|
||||
break;
|
||||
case Axis.vertical:
|
||||
childExtent = child.getMaxIntrinsicHeight(constraints.crossAxisExtent);
|
||||
childExtent = child!.getMaxIntrinsicHeight(constraints.crossAxisExtent);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -160,7 +156,7 @@ class RenderSliverFillRemaining extends RenderSliverSingleBoxAdapter {
|
|||
// that instead of potentially cutting off the child. This allows us to
|
||||
// safely specify a maxExtent.
|
||||
extent = math.max(extent, childExtent);
|
||||
child.layout(constraints.asBoxConstraints(
|
||||
child!.layout(constraints.asBoxConstraints(
|
||||
minExtent: extent,
|
||||
maxExtent: extent,
|
||||
));
|
||||
|
@ -182,7 +178,7 @@ class RenderSliverFillRemaining extends RenderSliverSingleBoxAdapter {
|
|||
hasVisualOverflow: extent > constraints.remainingPaintExtent || constraints.scrollOffset > 0.0,
|
||||
);
|
||||
if (child != null)
|
||||
setChildParentData(child, constraints, geometry);
|
||||
setChildParentData(child!, constraints, geometry!);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,7 +205,7 @@ class RenderSliverFillRemaining extends RenderSliverSingleBoxAdapter {
|
|||
class RenderSliverFillRemainingAndOverscroll extends RenderSliverSingleBoxAdapter {
|
||||
/// Creates a [RenderSliver] that wraps a non-scrollable [RenderBox] which is
|
||||
/// sized to fit the remaining space plus any overscroll in the viewport.
|
||||
RenderSliverFillRemainingAndOverscroll({ RenderBox child }) : super(child: child);
|
||||
RenderSliverFillRemainingAndOverscroll({ RenderBox? child }) : super(child: child);
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
|
@ -225,10 +221,10 @@ class RenderSliverFillRemainingAndOverscroll extends RenderSliverSingleBoxAdapte
|
|||
double childExtent;
|
||||
switch (constraints.axis) {
|
||||
case Axis.horizontal:
|
||||
childExtent = child.getMaxIntrinsicWidth(constraints.crossAxisExtent);
|
||||
childExtent = child!.getMaxIntrinsicWidth(constraints.crossAxisExtent);
|
||||
break;
|
||||
case Axis.vertical:
|
||||
childExtent = child.getMaxIntrinsicHeight(constraints.crossAxisExtent);
|
||||
childExtent = child!.getMaxIntrinsicHeight(constraints.crossAxisExtent);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -240,7 +236,7 @@ class RenderSliverFillRemainingAndOverscroll extends RenderSliverSingleBoxAdapte
|
|||
// size or overscrolling at the top of the scrollable (rather than at the
|
||||
// end where this sliver is).
|
||||
maxExtent = math.max(extent, maxExtent);
|
||||
child.layout(constraints.asBoxConstraints(minExtent: extent, maxExtent: maxExtent));
|
||||
child!.layout(constraints.asBoxConstraints(minExtent: extent, maxExtent: maxExtent));
|
||||
}
|
||||
|
||||
assert(extent.isFinite,
|
||||
|
@ -259,6 +255,6 @@ class RenderSliverFillRemainingAndOverscroll extends RenderSliverSingleBoxAdapte
|
|||
hasVisualOverflow: extent > constraints.remainingPaintExtent || constraints.scrollOffset > 0.0,
|
||||
);
|
||||
if (child != null)
|
||||
setChildParentData(child, constraints, geometry);
|
||||
setChildParentData(child!, constraints, geometry!);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -42,7 +40,7 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
|
|||
///
|
||||
/// The [childManager] argument must not be null.
|
||||
RenderSliverFixedExtentBoxAdaptor({
|
||||
@required RenderSliverBoxChildManager childManager,
|
||||
required RenderSliverBoxChildManager childManager,
|
||||
}) : super(childManager: childManager);
|
||||
|
||||
/// The main-axis extent of each item.
|
||||
|
@ -105,10 +103,10 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
|
|||
@protected
|
||||
double estimateMaxScrollOffset(
|
||||
SliverConstraints constraints, {
|
||||
int firstIndex,
|
||||
int lastIndex,
|
||||
double leadingScrollOffset,
|
||||
double trailingScrollOffset,
|
||||
int? firstIndex,
|
||||
int? lastIndex,
|
||||
double? leadingScrollOffset,
|
||||
double? trailingScrollOffset,
|
||||
}) {
|
||||
return childManager.estimateMaxScrollOffset(
|
||||
constraints,
|
||||
|
@ -145,7 +143,7 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
|
|||
}
|
||||
|
||||
int _calculateLeadingGarbage(int firstIndex) {
|
||||
RenderBox walker = firstChild;
|
||||
RenderBox? walker = firstChild;
|
||||
int leadingGarbage = 0;
|
||||
while(walker != null && indexOf(walker) < firstIndex){
|
||||
leadingGarbage += 1;
|
||||
|
@ -155,7 +153,7 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
|
|||
}
|
||||
|
||||
int _calculateTrailingGarbage(int targetLastIndex) {
|
||||
RenderBox walker = lastChild;
|
||||
RenderBox? walker = lastChild;
|
||||
int trailingGarbage = 0;
|
||||
while(walker != null && indexOf(walker) > targetLastIndex){
|
||||
trailingGarbage += 1;
|
||||
|
@ -184,12 +182,12 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
|
|||
);
|
||||
|
||||
final int firstIndex = getMinChildIndexForScrollOffset(scrollOffset, itemExtent);
|
||||
final int targetLastIndex = targetEndScrollOffset.isFinite ?
|
||||
final int? targetLastIndex = targetEndScrollOffset.isFinite ?
|
||||
getMaxChildIndexForScrollOffset(targetEndScrollOffset, itemExtent) : null;
|
||||
|
||||
if (firstChild != null) {
|
||||
final int leadingGarbage = _calculateLeadingGarbage(firstIndex);
|
||||
final int trailingGarbage = _calculateTrailingGarbage(targetLastIndex);
|
||||
final int trailingGarbage = _calculateTrailingGarbage(targetLastIndex!);
|
||||
collectGarbage(leadingGarbage, trailingGarbage);
|
||||
} else {
|
||||
collectGarbage(0, 0);
|
||||
|
@ -202,7 +200,10 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
|
|||
double max;
|
||||
if (childManager.childCount != null) {
|
||||
max = computeMaxScrollOffset(constraints, itemExtent);
|
||||
} else if (firstIndex <= 0) {
|
||||
// TODO(ianh): null-aware flow analysis flags the next two
|
||||
// branches as entirely dead code, and it's hard to argue with
|
||||
// its logic.
|
||||
} else if (firstIndex <= 0) { // ignore: dead_code
|
||||
max = 0.0;
|
||||
} else {
|
||||
// We will have to find it manually.
|
||||
|
@ -227,10 +228,10 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
|
|||
}
|
||||
}
|
||||
|
||||
RenderBox trailingChildWithLayout;
|
||||
RenderBox? trailingChildWithLayout;
|
||||
|
||||
for (int index = indexOf(firstChild) - 1; index >= firstIndex; --index) {
|
||||
final RenderBox child = insertAndLayoutLeadingChild(childConstraints);
|
||||
for (int index = indexOf(firstChild!) - 1; index >= firstIndex; --index) {
|
||||
final RenderBox? child = insertAndLayoutLeadingChild(childConstraints);
|
||||
if (child == null) {
|
||||
// Items before the previously first child are no longer present.
|
||||
// Reset the scroll offset to offset all items prior and up to the
|
||||
|
@ -245,15 +246,15 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
|
|||
}
|
||||
|
||||
if (trailingChildWithLayout == null) {
|
||||
firstChild.layout(childConstraints);
|
||||
final SliverMultiBoxAdaptorParentData childParentData = firstChild.parentData as SliverMultiBoxAdaptorParentData;
|
||||
firstChild!.layout(childConstraints);
|
||||
final SliverMultiBoxAdaptorParentData childParentData = firstChild!.parentData as SliverMultiBoxAdaptorParentData;
|
||||
childParentData.layoutOffset = indexToLayoutOffset(itemExtent, firstIndex);
|
||||
trailingChildWithLayout = firstChild;
|
||||
}
|
||||
|
||||
double estimatedMaxScrollOffset = double.infinity;
|
||||
for (int index = indexOf(trailingChildWithLayout) + 1; targetLastIndex == null || index <= targetLastIndex; ++index) {
|
||||
RenderBox child = childAfter(trailingChildWithLayout);
|
||||
for (int index = indexOf(trailingChildWithLayout!) + 1; targetLastIndex == null || index <= targetLastIndex; ++index) {
|
||||
RenderBox? child = childAfter(trailingChildWithLayout!);
|
||||
if (child == null || indexOf(child) != index) {
|
||||
child = insertAndLayoutChild(childConstraints, after: trailingChildWithLayout);
|
||||
if (child == null) {
|
||||
|
@ -268,16 +269,16 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
|
|||
assert(child != null);
|
||||
final SliverMultiBoxAdaptorParentData childParentData = child.parentData as SliverMultiBoxAdaptorParentData;
|
||||
assert(childParentData.index == index);
|
||||
childParentData.layoutOffset = indexToLayoutOffset(itemExtent, childParentData.index);
|
||||
childParentData.layoutOffset = indexToLayoutOffset(itemExtent, childParentData.index!);
|
||||
}
|
||||
|
||||
final int lastIndex = indexOf(lastChild);
|
||||
final int lastIndex = indexOf(lastChild!);
|
||||
final double leadingScrollOffset = indexToLayoutOffset(itemExtent, firstIndex);
|
||||
final double trailingScrollOffset = indexToLayoutOffset(itemExtent, lastIndex + 1);
|
||||
|
||||
assert(firstIndex == 0 || childScrollOffset(firstChild) - scrollOffset <= precisionErrorTolerance);
|
||||
assert(firstIndex == 0 || childScrollOffset(firstChild!)! - scrollOffset <= precisionErrorTolerance);
|
||||
assert(debugAssertChildListIsNonEmptyAndContiguous());
|
||||
assert(indexOf(firstChild) == firstIndex);
|
||||
assert(indexOf(firstChild!) == firstIndex);
|
||||
assert(targetLastIndex == null || lastIndex <= targetLastIndex);
|
||||
|
||||
estimatedMaxScrollOffset = math.min(
|
||||
|
@ -304,7 +305,7 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
|
|||
);
|
||||
|
||||
final double targetEndScrollOffsetForPaint = constraints.scrollOffset + constraints.remainingPaintExtent;
|
||||
final int targetLastIndexForPaint = targetEndScrollOffsetForPaint.isFinite ?
|
||||
final int? targetLastIndexForPaint = targetEndScrollOffsetForPaint.isFinite ?
|
||||
getMaxChildIndexForScrollOffset(targetEndScrollOffsetForPaint, itemExtent) : null;
|
||||
geometry = SliverGeometry(
|
||||
scrollExtent: estimatedMaxScrollOffset,
|
||||
|
@ -350,8 +351,8 @@ class RenderSliverFixedExtentList extends RenderSliverFixedExtentBoxAdaptor {
|
|||
///
|
||||
/// The [childManager] argument must not be null.
|
||||
RenderSliverFixedExtentList({
|
||||
@required RenderSliverBoxChildManager childManager,
|
||||
double itemExtent,
|
||||
required RenderSliverBoxChildManager childManager,
|
||||
required double itemExtent,
|
||||
}) : _itemExtent = itemExtent,
|
||||
super(childManager: childManager);
|
||||
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -27,10 +25,10 @@ import 'sliver_multi_box_adaptor.dart';
|
|||
class SliverGridGeometry {
|
||||
/// Creates an object that describes the placement of a child in a [RenderSliverGrid].
|
||||
const SliverGridGeometry({
|
||||
@required this.scrollOffset,
|
||||
@required this.crossAxisOffset,
|
||||
@required this.mainAxisExtent,
|
||||
@required this.crossAxisExtent,
|
||||
required this.scrollOffset,
|
||||
required this.crossAxisOffset,
|
||||
required this.mainAxisExtent,
|
||||
required this.crossAxisExtent,
|
||||
});
|
||||
|
||||
/// The scroll offset of the leading edge of the child relative to the leading
|
||||
|
@ -151,12 +149,12 @@ class SliverGridRegularTileLayout extends SliverGridLayout {
|
|||
/// All of the arguments must not be null and must not be negative. The
|
||||
/// `crossAxisCount` argument must be greater than zero.
|
||||
const SliverGridRegularTileLayout({
|
||||
@required this.crossAxisCount,
|
||||
@required this.mainAxisStride,
|
||||
@required this.crossAxisStride,
|
||||
@required this.childMainAxisExtent,
|
||||
@required this.childCrossAxisExtent,
|
||||
@required this.reverseCrossAxis,
|
||||
required this.crossAxisCount,
|
||||
required this.mainAxisStride,
|
||||
required this.crossAxisStride,
|
||||
required this.childMainAxisExtent,
|
||||
required this.childCrossAxisExtent,
|
||||
required this.reverseCrossAxis,
|
||||
}) : assert(crossAxisCount != null && crossAxisCount > 0),
|
||||
assert(mainAxisStride != null && mainAxisStride >= 0),
|
||||
assert(crossAxisStride != null && crossAxisStride >= 0),
|
||||
|
@ -296,7 +294,7 @@ class SliverGridDelegateWithFixedCrossAxisCount extends SliverGridDelegate {
|
|||
/// `crossAxisSpacing` arguments must not be negative. The `crossAxisCount`
|
||||
/// and `childAspectRatio` arguments must be greater than zero.
|
||||
const SliverGridDelegateWithFixedCrossAxisCount({
|
||||
@required this.crossAxisCount,
|
||||
required this.crossAxisCount,
|
||||
this.mainAxisSpacing = 0.0,
|
||||
this.crossAxisSpacing = 0.0,
|
||||
this.childAspectRatio = 1.0,
|
||||
|
@ -383,7 +381,7 @@ class SliverGridDelegateWithMaxCrossAxisExtent extends SliverGridDelegate {
|
|||
/// [mainAxisSpacing], and [crossAxisSpacing] arguments must not be negative.
|
||||
/// The [childAspectRatio] argument must be greater than zero.
|
||||
const SliverGridDelegateWithMaxCrossAxisExtent({
|
||||
@required this.maxCrossAxisExtent,
|
||||
required this.maxCrossAxisExtent,
|
||||
this.mainAxisSpacing = 0.0,
|
||||
this.crossAxisSpacing = 0.0,
|
||||
this.childAspectRatio = 1.0,
|
||||
|
@ -457,7 +455,7 @@ class SliverGridParentData extends SliverMultiBoxAdaptorParentData {
|
|||
/// the parent to the left-most edge of the child. If the scroll axis is
|
||||
/// horizontal, this offset is from the top-most edge of the parent to the
|
||||
/// top-most edge of the child.
|
||||
double crossAxisOffset;
|
||||
double? crossAxisOffset;
|
||||
|
||||
@override
|
||||
String toString() => 'crossAxisOffset=$crossAxisOffset; ${super.toString()}';
|
||||
|
@ -481,8 +479,8 @@ class RenderSliverGrid extends RenderSliverMultiBoxAdaptor {
|
|||
///
|
||||
/// The [childManager] and [gridDelegate] arguments must not be null.
|
||||
RenderSliverGrid({
|
||||
@required RenderSliverBoxChildManager childManager,
|
||||
@required SliverGridDelegate gridDelegate,
|
||||
required RenderSliverBoxChildManager childManager,
|
||||
required SliverGridDelegate gridDelegate,
|
||||
}) : assert(gridDelegate != null),
|
||||
_gridDelegate = gridDelegate,
|
||||
super(childManager: childManager);
|
||||
|
@ -509,7 +507,7 @@ class RenderSliverGrid extends RenderSliverMultiBoxAdaptor {
|
|||
@override
|
||||
double childCrossAxisPosition(RenderBox child) {
|
||||
final SliverGridParentData childParentData = child.parentData as SliverGridParentData;
|
||||
return childParentData.crossAxisOffset;
|
||||
return childParentData.crossAxisOffset!;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -527,16 +525,16 @@ class RenderSliverGrid extends RenderSliverMultiBoxAdaptor {
|
|||
final SliverGridLayout layout = _gridDelegate.getLayout(constraints);
|
||||
|
||||
final int firstIndex = layout.getMinChildIndexForScrollOffset(scrollOffset);
|
||||
final int targetLastIndex = targetEndScrollOffset.isFinite ?
|
||||
final int? targetLastIndex = targetEndScrollOffset.isFinite ?
|
||||
layout.getMaxChildIndexForScrollOffset(targetEndScrollOffset) : null;
|
||||
|
||||
if (firstChild != null) {
|
||||
final int oldFirstIndex = indexOf(firstChild);
|
||||
final int oldLastIndex = indexOf(lastChild);
|
||||
final int leadingGarbage = (firstIndex - oldFirstIndex).clamp(0, childCount) as int;
|
||||
final int oldFirstIndex = indexOf(firstChild!);
|
||||
final int oldLastIndex = indexOf(lastChild!);
|
||||
final int leadingGarbage = (firstIndex - oldFirstIndex).clamp(0, childCount);
|
||||
final int trailingGarbage = targetLastIndex == null
|
||||
? 0
|
||||
: ((oldLastIndex - targetLastIndex).clamp(0, childCount) as int);
|
||||
: (oldLastIndex - targetLastIndex).clamp(0, childCount);
|
||||
collectGarbage(leadingGarbage, trailingGarbage);
|
||||
} else {
|
||||
collectGarbage(0, 0);
|
||||
|
@ -559,13 +557,13 @@ class RenderSliverGrid extends RenderSliverMultiBoxAdaptor {
|
|||
}
|
||||
}
|
||||
|
||||
RenderBox trailingChildWithLayout;
|
||||
RenderBox? trailingChildWithLayout;
|
||||
|
||||
for (int index = indexOf(firstChild) - 1; index >= firstIndex; --index) {
|
||||
for (int index = indexOf(firstChild!) - 1; index >= firstIndex; --index) {
|
||||
final SliverGridGeometry gridGeometry = layout.getGeometryForChildIndex(index);
|
||||
final RenderBox child = insertAndLayoutLeadingChild(
|
||||
gridGeometry.getBoxConstraints(constraints),
|
||||
);
|
||||
)!;
|
||||
final SliverGridParentData childParentData = child.parentData as SliverGridParentData;
|
||||
childParentData.layoutOffset = gridGeometry.scrollOffset;
|
||||
childParentData.crossAxisOffset = gridGeometry.crossAxisOffset;
|
||||
|
@ -575,17 +573,17 @@ class RenderSliverGrid extends RenderSliverMultiBoxAdaptor {
|
|||
}
|
||||
|
||||
if (trailingChildWithLayout == null) {
|
||||
firstChild.layout(firstChildGridGeometry.getBoxConstraints(constraints));
|
||||
final SliverGridParentData childParentData = firstChild.parentData as SliverGridParentData;
|
||||
firstChild!.layout(firstChildGridGeometry.getBoxConstraints(constraints));
|
||||
final SliverGridParentData childParentData = firstChild!.parentData as SliverGridParentData;
|
||||
childParentData.layoutOffset = firstChildGridGeometry.scrollOffset;
|
||||
childParentData.crossAxisOffset = firstChildGridGeometry.crossAxisOffset;
|
||||
trailingChildWithLayout = firstChild;
|
||||
}
|
||||
|
||||
for (int index = indexOf(trailingChildWithLayout) + 1; targetLastIndex == null || index <= targetLastIndex; ++index) {
|
||||
for (int index = indexOf(trailingChildWithLayout!) + 1; targetLastIndex == null || index <= targetLastIndex; ++index) {
|
||||
final SliverGridGeometry gridGeometry = layout.getGeometryForChildIndex(index);
|
||||
final BoxConstraints childConstraints = gridGeometry.getBoxConstraints(constraints);
|
||||
RenderBox child = childAfter(trailingChildWithLayout);
|
||||
RenderBox? child = childAfter(trailingChildWithLayout!);
|
||||
if (child == null || indexOf(child) != index) {
|
||||
child = insertAndLayoutChild(childConstraints, after: trailingChildWithLayout);
|
||||
if (child == null) {
|
||||
|
@ -604,11 +602,11 @@ class RenderSliverGrid extends RenderSliverMultiBoxAdaptor {
|
|||
trailingScrollOffset = math.max(trailingScrollOffset, gridGeometry.trailingScrollOffset);
|
||||
}
|
||||
|
||||
final int lastIndex = indexOf(lastChild);
|
||||
final int lastIndex = indexOf(lastChild!);
|
||||
|
||||
assert(childScrollOffset(firstChild) <= scrollOffset);
|
||||
assert(childScrollOffset(firstChild!)! <= scrollOffset);
|
||||
assert(debugAssertChildListIsNonEmptyAndContiguous());
|
||||
assert(indexOf(firstChild) == firstIndex);
|
||||
assert(indexOf(firstChild!) == firstIndex);
|
||||
assert(targetLastIndex == null || lastIndex <= targetLastIndex);
|
||||
|
||||
final double estimatedTotalExtent = childManager.estimateMaxScrollOffset(
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'box.dart';
|
||||
|
@ -41,7 +39,7 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
|
|||
///
|
||||
/// The [childManager] argument must not be null.
|
||||
RenderSliverList({
|
||||
@required RenderSliverBoxChildManager childManager,
|
||||
required RenderSliverBoxChildManager childManager,
|
||||
}) : super(childManager: childManager);
|
||||
|
||||
@override
|
||||
|
@ -91,9 +89,9 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
|
|||
// These variables track the range of children that we have laid out. Within
|
||||
// this range, the children have consecutive indices. Outside this range,
|
||||
// it's possible for a child to get removed without notice.
|
||||
RenderBox leadingChildWithLayout, trailingChildWithLayout;
|
||||
RenderBox? leadingChildWithLayout, trailingChildWithLayout;
|
||||
|
||||
RenderBox earliestUsefulChild = firstChild;
|
||||
RenderBox? earliestUsefulChild = firstChild;
|
||||
|
||||
// A firstChild with null layout offset is likely a result of children
|
||||
// reordering.
|
||||
|
@ -101,10 +99,10 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
|
|||
// We rely on firstChild to have accurate layout offset. In the case of null
|
||||
// layout offset, we have to find the first child that has valid layout
|
||||
// offset.
|
||||
if (childScrollOffset(firstChild) == null) {
|
||||
if (childScrollOffset(firstChild!) == null) {
|
||||
int leadingChildrenWithoutLayoutOffset = 0;
|
||||
while (childScrollOffset(earliestUsefulChild) == null) {
|
||||
earliestUsefulChild = childAfter(firstChild);
|
||||
while (childScrollOffset(earliestUsefulChild!) == null) {
|
||||
earliestUsefulChild = childAfter(firstChild!);
|
||||
leadingChildrenWithoutLayoutOffset += 1;
|
||||
}
|
||||
// We should be able to destroy children with null layout offset safely,
|
||||
|
@ -115,20 +113,20 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
|
|||
|
||||
// Find the last child that is at or before the scrollOffset.
|
||||
earliestUsefulChild = firstChild;
|
||||
for (double earliestScrollOffset = childScrollOffset(earliestUsefulChild);
|
||||
for (double earliestScrollOffset = childScrollOffset(earliestUsefulChild!)!;
|
||||
earliestScrollOffset > scrollOffset;
|
||||
earliestScrollOffset = childScrollOffset(earliestUsefulChild)) {
|
||||
earliestScrollOffset = childScrollOffset(earliestUsefulChild)!) {
|
||||
// We have to add children before the earliestUsefulChild.
|
||||
earliestUsefulChild = insertAndLayoutLeadingChild(childConstraints, parentUsesSize: true);
|
||||
if (earliestUsefulChild == null) {
|
||||
final SliverMultiBoxAdaptorParentData childParentData = firstChild.parentData as SliverMultiBoxAdaptorParentData;
|
||||
final SliverMultiBoxAdaptorParentData childParentData = firstChild!.parentData as SliverMultiBoxAdaptorParentData;
|
||||
childParentData.layoutOffset = 0.0;
|
||||
|
||||
if (scrollOffset == 0.0) {
|
||||
// insertAndLayoutLeadingChild only lays out the children before
|
||||
// firstChild. In this case, nothing has been laid out. We have
|
||||
// to lay out firstChild manually.
|
||||
firstChild.layout(childConstraints, parentUsesSize: true);
|
||||
firstChild!.layout(childConstraints, parentUsesSize: true);
|
||||
earliestUsefulChild = firstChild;
|
||||
leadingChildWithLayout = earliestUsefulChild;
|
||||
trailingChildWithLayout ??= earliestUsefulChild;
|
||||
|
@ -144,7 +142,7 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
|
|||
}
|
||||
}
|
||||
|
||||
final double firstChildScrollOffset = earliestScrollOffset - paintExtentOf(firstChild);
|
||||
final double firstChildScrollOffset = earliestScrollOffset - paintExtentOf(firstChild!);
|
||||
// firstChildScrollOffset may contain double precision error
|
||||
if (firstChildScrollOffset < -precisionErrorTolerance) {
|
||||
// Let's assume there is no child before the first child. We will
|
||||
|
@ -152,7 +150,7 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
|
|||
geometry = SliverGeometry(
|
||||
scrollOffsetCorrection: -firstChildScrollOffset,
|
||||
);
|
||||
final SliverMultiBoxAdaptorParentData childParentData = firstChild.parentData as SliverMultiBoxAdaptorParentData;
|
||||
final SliverMultiBoxAdaptorParentData childParentData = firstChild!.parentData as SliverMultiBoxAdaptorParentData;
|
||||
childParentData.layoutOffset = 0.0;
|
||||
return;
|
||||
}
|
||||
|
@ -164,22 +162,22 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
|
|||
trailingChildWithLayout ??= earliestUsefulChild;
|
||||
}
|
||||
|
||||
assert(childScrollOffset(firstChild) > -precisionErrorTolerance);
|
||||
assert(childScrollOffset(firstChild!)! > -precisionErrorTolerance);
|
||||
|
||||
// If the scroll offset is at zero, we should make sure we are
|
||||
// actually at the beginning of the list.
|
||||
if (scrollOffset < precisionErrorTolerance) {
|
||||
// We iterate from the firstChild in case the leading child has a 0 paint
|
||||
// extent.
|
||||
while (indexOf(firstChild) > 0) {
|
||||
final double earliestScrollOffset = childScrollOffset(firstChild);
|
||||
while (indexOf(firstChild!) > 0) {
|
||||
final double earliestScrollOffset = childScrollOffset(firstChild!)!;
|
||||
// We correct one child at a time. If there are more children before
|
||||
// the earliestUsefulChild, we will correct it once the scroll offset
|
||||
// reaches zero again.
|
||||
earliestUsefulChild = insertAndLayoutLeadingChild(childConstraints, parentUsesSize: true);
|
||||
assert(earliestUsefulChild != null);
|
||||
final double firstChildScrollOffset = earliestScrollOffset - paintExtentOf(firstChild);
|
||||
final SliverMultiBoxAdaptorParentData childParentData = firstChild.parentData as SliverMultiBoxAdaptorParentData;
|
||||
final double firstChildScrollOffset = earliestScrollOffset - paintExtentOf(firstChild!);
|
||||
final SliverMultiBoxAdaptorParentData childParentData = firstChild!.parentData as SliverMultiBoxAdaptorParentData;
|
||||
childParentData.layoutOffset = 0.0;
|
||||
// We only need to correct if the leading child actually has a
|
||||
// paint extent.
|
||||
|
@ -200,11 +198,11 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
|
|||
// scroll offset.
|
||||
|
||||
assert(earliestUsefulChild == firstChild);
|
||||
assert(childScrollOffset(earliestUsefulChild) <= scrollOffset);
|
||||
assert(childScrollOffset(earliestUsefulChild!)! <= scrollOffset);
|
||||
|
||||
// Make sure we've laid out at least one child.
|
||||
if (leadingChildWithLayout == null) {
|
||||
earliestUsefulChild.layout(childConstraints, parentUsesSize: true);
|
||||
earliestUsefulChild!.layout(childConstraints, parentUsesSize: true);
|
||||
leadingChildWithLayout = earliestUsefulChild;
|
||||
trailingChildWithLayout = earliestUsefulChild;
|
||||
}
|
||||
|
@ -215,20 +213,20 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
|
|||
// that some children beyond that one have also been laid out.
|
||||
|
||||
bool inLayoutRange = true;
|
||||
RenderBox child = earliestUsefulChild;
|
||||
int index = indexOf(child);
|
||||
double endScrollOffset = childScrollOffset(child) + paintExtentOf(child);
|
||||
RenderBox? child = earliestUsefulChild;
|
||||
int index = indexOf(child!);
|
||||
double endScrollOffset = childScrollOffset(child)! + paintExtentOf(child);
|
||||
bool advance() { // returns true if we advanced, false if we have no more children
|
||||
// This function is used in two different places below, to avoid code duplication.
|
||||
assert(child != null);
|
||||
if (child == trailingChildWithLayout)
|
||||
inLayoutRange = false;
|
||||
child = childAfter(child);
|
||||
child = childAfter(child!);
|
||||
if (child == null)
|
||||
inLayoutRange = false;
|
||||
index += 1;
|
||||
if (!inLayoutRange) {
|
||||
if (child == null || indexOf(child) != index) {
|
||||
if (child == null || indexOf(child!) != index) {
|
||||
// We are missing a child. Insert it (and lay it out) if possible.
|
||||
child = insertAndLayoutChild(childConstraints,
|
||||
after: trailingChildWithLayout,
|
||||
|
@ -240,15 +238,15 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
|
|||
}
|
||||
} else {
|
||||
// Lay out the child.
|
||||
child.layout(childConstraints, parentUsesSize: true);
|
||||
child!.layout(childConstraints, parentUsesSize: true);
|
||||
}
|
||||
trailingChildWithLayout = child;
|
||||
}
|
||||
assert(child != null);
|
||||
final SliverMultiBoxAdaptorParentData childParentData = child.parentData as SliverMultiBoxAdaptorParentData;
|
||||
final SliverMultiBoxAdaptorParentData childParentData = child!.parentData as SliverMultiBoxAdaptorParentData;
|
||||
childParentData.layoutOffset = endScrollOffset;
|
||||
assert(childParentData.index == index);
|
||||
endScrollOffset = childScrollOffset(child) + paintExtentOf(child);
|
||||
endScrollOffset = childScrollOffset(child!)! + paintExtentOf(child!);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -261,7 +259,7 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
|
|||
// we want to make sure we keep the last child around so we know the end scroll offset
|
||||
collectGarbage(leadingGarbage - 1, 0);
|
||||
assert(firstChild == lastChild);
|
||||
final double extent = childScrollOffset(lastChild) + paintExtentOf(lastChild);
|
||||
final double extent = childScrollOffset(lastChild!)! + paintExtentOf(lastChild!);
|
||||
geometry = SliverGeometry(
|
||||
scrollExtent: extent,
|
||||
paintExtent: 0.0,
|
||||
|
@ -281,10 +279,10 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
|
|||
|
||||
// Finally count up all the remaining children and label them as garbage.
|
||||
if (child != null) {
|
||||
child = childAfter(child);
|
||||
child = childAfter(child!);
|
||||
while (child != null) {
|
||||
trailingGarbage += 1;
|
||||
child = childAfter(child);
|
||||
child = childAfter(child!);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,21 +298,21 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
|
|||
} else {
|
||||
estimatedMaxScrollOffset = childManager.estimateMaxScrollOffset(
|
||||
constraints,
|
||||
firstIndex: indexOf(firstChild),
|
||||
lastIndex: indexOf(lastChild),
|
||||
leadingScrollOffset: childScrollOffset(firstChild),
|
||||
firstIndex: indexOf(firstChild!),
|
||||
lastIndex: indexOf(lastChild!),
|
||||
leadingScrollOffset: childScrollOffset(firstChild!),
|
||||
trailingScrollOffset: endScrollOffset,
|
||||
);
|
||||
assert(estimatedMaxScrollOffset >= endScrollOffset - childScrollOffset(firstChild));
|
||||
assert(estimatedMaxScrollOffset >= endScrollOffset - childScrollOffset(firstChild!)!);
|
||||
}
|
||||
final double paintExtent = calculatePaintOffset(
|
||||
constraints,
|
||||
from: childScrollOffset(firstChild),
|
||||
from: childScrollOffset(firstChild!)!,
|
||||
to: endScrollOffset,
|
||||
);
|
||||
final double cacheExtent = calculateCacheOffset(
|
||||
constraints,
|
||||
from: childScrollOffset(firstChild),
|
||||
from: childScrollOffset(firstChild!)!,
|
||||
to: endScrollOffset,
|
||||
);
|
||||
final double targetEndScrollOffsetForPaint = constraints.scrollOffset + constraints.remainingPaintExtent;
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
@ -44,7 +42,7 @@ abstract class RenderSliverBoxChildManager {
|
|||
/// the [RenderSliverMultiBoxAdaptor] object if they were not created during
|
||||
/// this frame and have not yet been updated during this frame. It is not
|
||||
/// valid to add any other children to this render object.
|
||||
void createChild(int index, { @required RenderBox after });
|
||||
void createChild(int index, { required RenderBox? after });
|
||||
|
||||
/// Remove the given child from the child list.
|
||||
///
|
||||
|
@ -64,10 +62,10 @@ abstract class RenderSliverBoxChildManager {
|
|||
/// index.
|
||||
double estimateMaxScrollOffset(
|
||||
SliverConstraints constraints, {
|
||||
int firstIndex,
|
||||
int lastIndex,
|
||||
double leadingScrollOffset,
|
||||
double trailingScrollOffset,
|
||||
int? firstIndex,
|
||||
int? lastIndex,
|
||||
double? leadingScrollOffset,
|
||||
double? trailingScrollOffset,
|
||||
});
|
||||
|
||||
/// Called to obtain a precise measure of the total number of children.
|
||||
|
@ -146,7 +144,7 @@ mixin RenderSliverWithKeepAliveMixin implements RenderSliver {
|
|||
/// Parent data structure used by [RenderSliverMultiBoxAdaptor].
|
||||
class SliverMultiBoxAdaptorParentData extends SliverLogicalParentData with ContainerParentDataMixin<RenderBox>, KeepAliveParentDataMixin {
|
||||
/// The index of this child according to the [RenderSliverBoxChildManager].
|
||||
int index;
|
||||
int? index;
|
||||
|
||||
@override
|
||||
bool get keptAlive => _keptAlive;
|
||||
|
@ -189,7 +187,7 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
///
|
||||
/// The [childManager] argument must not be null.
|
||||
RenderSliverMultiBoxAdaptor({
|
||||
@required RenderSliverBoxChildManager childManager,
|
||||
required RenderSliverBoxChildManager childManager,
|
||||
}) : assert(childManager != null),
|
||||
_childManager = childManager {
|
||||
assert(() {
|
||||
|
@ -217,7 +215,7 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
/// The nodes being kept alive despite not being visible.
|
||||
final Map<int, RenderBox> _keepAliveBucket = <int, RenderBox>{};
|
||||
|
||||
List<RenderBox> _debugDanglingKeepAlives;
|
||||
late List<RenderBox> _debugDanglingKeepAlives;
|
||||
|
||||
/// Indicates whether integrity check is enabled.
|
||||
///
|
||||
|
@ -253,7 +251,7 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
/// This has no effect in release builds.
|
||||
bool _debugVerifyChildOrder(){
|
||||
if (_debugChildIntegrityEnabled) {
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
int index;
|
||||
while (child != null) {
|
||||
index = indexOf(child);
|
||||
|
@ -265,7 +263,7 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
}
|
||||
|
||||
@override
|
||||
void insert(RenderBox child, { RenderBox after }) {
|
||||
void insert(RenderBox child, { RenderBox? after }) {
|
||||
assert(!_keepAliveBucket.containsValue(child));
|
||||
super.insert(child, after: after);
|
||||
assert(firstChild != null);
|
||||
|
@ -273,7 +271,7 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
}
|
||||
|
||||
@override
|
||||
void move(RenderBox child, { RenderBox after }) {
|
||||
void move(RenderBox child, { RenderBox? after }) {
|
||||
// There are two scenarios:
|
||||
//
|
||||
// 1. The child is not keptAlive.
|
||||
|
@ -307,10 +305,10 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
// removed by updateChild. Thus, it is ok to overwrite it.
|
||||
assert(() {
|
||||
if (_keepAliveBucket.containsKey(childParentData.index))
|
||||
_debugDanglingKeepAlives.add(_keepAliveBucket[childParentData.index]);
|
||||
_debugDanglingKeepAlives.add(_keepAliveBucket[childParentData.index]!);
|
||||
return true;
|
||||
}());
|
||||
_keepAliveBucket[childParentData.index] = child;
|
||||
_keepAliveBucket[childParentData.index!] = child;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,11 +335,11 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
_keepAliveBucket.clear();
|
||||
}
|
||||
|
||||
void _createOrObtainChild(int index, { RenderBox after }) {
|
||||
void _createOrObtainChild(int index, { required RenderBox? after }) {
|
||||
invokeLayoutCallback<SliverConstraints>((SliverConstraints constraints) {
|
||||
assert(constraints == this.constraints);
|
||||
if (_keepAliveBucket.containsKey(index)) {
|
||||
final RenderBox child = _keepAliveBucket.remove(index);
|
||||
final RenderBox child = _keepAliveBucket.remove(index)!;
|
||||
final SliverMultiBoxAdaptorParentData childParentData = child.parentData as SliverMultiBoxAdaptorParentData;
|
||||
assert(childParentData._keptAlive);
|
||||
dropChild(child);
|
||||
|
@ -359,7 +357,7 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
if (childParentData.keepAlive) {
|
||||
assert(!childParentData._keptAlive);
|
||||
remove(child);
|
||||
_keepAliveBucket[childParentData.index] = child;
|
||||
_keepAliveBucket[childParentData.index!] = child;
|
||||
child.parentData = childParentData;
|
||||
super.adoptChild(child);
|
||||
childParentData._keptAlive = true;
|
||||
|
@ -425,8 +423,8 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
_createOrObtainChild(index, after: null);
|
||||
if (firstChild != null) {
|
||||
assert(firstChild == lastChild);
|
||||
assert(indexOf(firstChild) == index);
|
||||
final SliverMultiBoxAdaptorParentData firstChildParentData = firstChild.parentData as SliverMultiBoxAdaptorParentData;
|
||||
assert(indexOf(firstChild!) == index);
|
||||
final SliverMultiBoxAdaptorParentData firstChildParentData = firstChild!.parentData as SliverMultiBoxAdaptorParentData;
|
||||
firstChildParentData.layoutOffset = layoutOffset;
|
||||
return true;
|
||||
}
|
||||
|
@ -448,15 +446,15 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
/// during this layout pass. No child should be added during that call except
|
||||
/// for the one that is created and returned by `createChild`.
|
||||
@protected
|
||||
RenderBox insertAndLayoutLeadingChild(
|
||||
RenderBox? insertAndLayoutLeadingChild(
|
||||
BoxConstraints childConstraints, {
|
||||
bool parentUsesSize = false,
|
||||
}) {
|
||||
assert(_debugAssertChildListLocked());
|
||||
final int index = indexOf(firstChild) - 1;
|
||||
final int index = indexOf(firstChild!) - 1;
|
||||
_createOrObtainChild(index, after: null);
|
||||
if (indexOf(firstChild) == index) {
|
||||
firstChild.layout(childConstraints, parentUsesSize: parentUsesSize);
|
||||
if (indexOf(firstChild!) == index) {
|
||||
firstChild!.layout(childConstraints, parentUsesSize: parentUsesSize);
|
||||
return firstChild;
|
||||
}
|
||||
childManager.setDidUnderflow(true);
|
||||
|
@ -476,16 +474,16 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
/// Children after the `after` child may be removed in the process. Only the
|
||||
/// new child may be added.
|
||||
@protected
|
||||
RenderBox insertAndLayoutChild(
|
||||
RenderBox? insertAndLayoutChild(
|
||||
BoxConstraints childConstraints, {
|
||||
@required RenderBox after,
|
||||
required RenderBox? after,
|
||||
bool parentUsesSize = false,
|
||||
}) {
|
||||
assert(_debugAssertChildListLocked());
|
||||
assert(after != null);
|
||||
final int index = indexOf(after) + 1;
|
||||
final int index = indexOf(after!) + 1;
|
||||
_createOrObtainChild(index, after: after);
|
||||
final RenderBox child = childAfter(after);
|
||||
final RenderBox? child = childAfter(after);
|
||||
if (child != null && indexOf(child) == index) {
|
||||
child.layout(childConstraints, parentUsesSize: parentUsesSize);
|
||||
return child;
|
||||
|
@ -509,11 +507,11 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
assert(childCount >= leadingGarbage + trailingGarbage);
|
||||
invokeLayoutCallback<SliverConstraints>((SliverConstraints constraints) {
|
||||
while (leadingGarbage > 0) {
|
||||
_destroyOrCacheChild(firstChild);
|
||||
_destroyOrCacheChild(firstChild!);
|
||||
leadingGarbage -= 1;
|
||||
}
|
||||
while (trailingGarbage > 0) {
|
||||
_destroyOrCacheChild(lastChild);
|
||||
_destroyOrCacheChild(lastChild!);
|
||||
trailingGarbage -= 1;
|
||||
}
|
||||
// Ask the child manager to remove the children that are no longer being
|
||||
|
@ -536,7 +534,7 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
assert(child != null);
|
||||
final SliverMultiBoxAdaptorParentData childParentData = child.parentData as SliverMultiBoxAdaptorParentData;
|
||||
assert(childParentData.index != null);
|
||||
return childParentData.index;
|
||||
return childParentData.index!;
|
||||
}
|
||||
|
||||
/// Returns the dimension of the given child in the main axis, as given by the
|
||||
|
@ -551,12 +549,11 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
case Axis.vertical:
|
||||
return child.size.height;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(SliverHitTestResult result, { @required double mainAxisPosition, @required double crossAxisPosition }) {
|
||||
RenderBox child = lastChild;
|
||||
bool hitTestChildren(SliverHitTestResult result, { required double mainAxisPosition, required double crossAxisPosition }) {
|
||||
RenderBox? child = lastChild;
|
||||
final BoxHitTestResult boxResult = BoxHitTestResult.wrap(result);
|
||||
while (child != null) {
|
||||
if (hitTestBoxChild(boxResult, child, mainAxisPosition: mainAxisPosition, crossAxisPosition: crossAxisPosition))
|
||||
|
@ -568,11 +565,11 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
|
||||
@override
|
||||
double childMainAxisPosition(RenderBox child) {
|
||||
return childScrollOffset(child) - constraints.scrollOffset;
|
||||
return childScrollOffset(child)! - constraints.scrollOffset;
|
||||
}
|
||||
|
||||
@override
|
||||
double childScrollOffset(RenderObject child) {
|
||||
double? childScrollOffset(RenderObject child) {
|
||||
assert(child != null);
|
||||
assert(child.parent == this);
|
||||
final SliverMultiBoxAdaptorParentData childParentData = child.parentData as SliverMultiBoxAdaptorParentData;
|
||||
|
@ -604,7 +601,7 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
case AxisDirection.up:
|
||||
mainAxisUnit = const Offset(0.0, -1.0);
|
||||
crossAxisUnit = const Offset(1.0, 0.0);
|
||||
originOffset = offset + Offset(0.0, geometry.paintExtent);
|
||||
originOffset = offset + Offset(0.0, geometry!.paintExtent);
|
||||
addExtent = true;
|
||||
break;
|
||||
case AxisDirection.right:
|
||||
|
@ -622,13 +619,13 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
case AxisDirection.left:
|
||||
mainAxisUnit = const Offset(-1.0, 0.0);
|
||||
crossAxisUnit = const Offset(0.0, 1.0);
|
||||
originOffset = offset + Offset(geometry.paintExtent, 0.0);
|
||||
originOffset = offset + Offset(geometry!.paintExtent, 0.0);
|
||||
addExtent = true;
|
||||
break;
|
||||
}
|
||||
assert(mainAxisUnit != null);
|
||||
assert(addExtent != null);
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
final double mainAxisDelta = childMainAxisPosition(child);
|
||||
final double crossAxisDelta = childCrossAxisPosition(child);
|
||||
|
@ -651,7 +648,7 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(DiagnosticsNode.message(firstChild != null ? 'currently live children: ${indexOf(firstChild)} to ${indexOf(lastChild)}' : 'no children current live'));
|
||||
properties.add(DiagnosticsNode.message(firstChild != null ? 'currently live children: ${indexOf(firstChild!)} to ${indexOf(lastChild!)}' : 'no children current live'));
|
||||
}
|
||||
|
||||
/// Asserts that the reified child list is not empty and has a contiguous
|
||||
|
@ -661,8 +658,8 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
bool debugAssertChildListIsNonEmptyAndContiguous() {
|
||||
assert(() {
|
||||
assert(firstChild != null);
|
||||
int index = indexOf(firstChild);
|
||||
RenderBox child = childAfter(firstChild);
|
||||
int index = indexOf(firstChild!);
|
||||
RenderBox? child = childAfter(firstChild!);
|
||||
while (child != null) {
|
||||
index += 1;
|
||||
assert(indexOf(child) == index);
|
||||
|
@ -677,9 +674,9 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
List<DiagnosticsNode> debugDescribeChildren() {
|
||||
final List<DiagnosticsNode> children = <DiagnosticsNode>[];
|
||||
if (firstChild != null) {
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (true) {
|
||||
final SliverMultiBoxAdaptorParentData childParentData = child.parentData as SliverMultiBoxAdaptorParentData;
|
||||
final SliverMultiBoxAdaptorParentData childParentData = child!.parentData as SliverMultiBoxAdaptorParentData;
|
||||
children.add(child.toDiagnosticsNode(name: 'child with index ${childParentData.index}'));
|
||||
if (child == lastChild)
|
||||
break;
|
||||
|
@ -689,7 +686,7 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
|
|||
if (_keepAliveBucket.isNotEmpty) {
|
||||
final List<int> indices = _keepAliveBucket.keys.toList()..sort();
|
||||
for (final int index in indices) {
|
||||
children.add(_keepAliveBucket[index].toDiagnosticsNode(
|
||||
children.add(_keepAliveBucket[index]!.toDiagnosticsNode(
|
||||
name: 'child with index $index (kept alive but not laid out)',
|
||||
style: DiagnosticsTreeStyle.offstage,
|
||||
));
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -34,7 +32,7 @@ abstract class RenderSliverEdgeInsetsPadding extends RenderSliver with RenderObj
|
|||
/// bottom. These values are not affected by the [TextDirection].
|
||||
///
|
||||
/// Must not be null or contain negative values when [performLayout] is called.
|
||||
EdgeInsets get resolvedPadding;
|
||||
EdgeInsets? get resolvedPadding;
|
||||
|
||||
/// The padding in the scroll direction on the side nearest the 0.0 scroll direction.
|
||||
///
|
||||
|
@ -47,15 +45,14 @@ abstract class RenderSliverEdgeInsetsPadding extends RenderSliver with RenderObj
|
|||
assert(resolvedPadding != null);
|
||||
switch (applyGrowthDirectionToAxisDirection(constraints.axisDirection, constraints.growthDirection)) {
|
||||
case AxisDirection.up:
|
||||
return resolvedPadding.bottom;
|
||||
return resolvedPadding!.bottom;
|
||||
case AxisDirection.right:
|
||||
return resolvedPadding.left;
|
||||
return resolvedPadding!.left;
|
||||
case AxisDirection.down:
|
||||
return resolvedPadding.top;
|
||||
return resolvedPadding!.top;
|
||||
case AxisDirection.left:
|
||||
return resolvedPadding.right;
|
||||
return resolvedPadding!.right;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// The padding in the scroll direction on the side furthest from the 0.0 scroll offset.
|
||||
|
@ -69,15 +66,14 @@ abstract class RenderSliverEdgeInsetsPadding extends RenderSliver with RenderObj
|
|||
assert(resolvedPadding != null);
|
||||
switch (applyGrowthDirectionToAxisDirection(constraints.axisDirection, constraints.growthDirection)) {
|
||||
case AxisDirection.up:
|
||||
return resolvedPadding.top;
|
||||
return resolvedPadding!.top;
|
||||
case AxisDirection.right:
|
||||
return resolvedPadding.right;
|
||||
return resolvedPadding!.right;
|
||||
case AxisDirection.down:
|
||||
return resolvedPadding.bottom;
|
||||
return resolvedPadding!.bottom;
|
||||
case AxisDirection.left:
|
||||
return resolvedPadding.left;
|
||||
return resolvedPadding!.left;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// The total padding in the [SliverConstraints.axisDirection]. (In other
|
||||
|
@ -90,7 +86,7 @@ abstract class RenderSliverEdgeInsetsPadding extends RenderSliver with RenderObj
|
|||
assert(constraints != null);
|
||||
assert(constraints.axis != null);
|
||||
assert(resolvedPadding != null);
|
||||
return resolvedPadding.along(constraints.axis);
|
||||
return resolvedPadding!.along(constraints.axis);
|
||||
}
|
||||
|
||||
/// The total padding in the cross-axis direction. (In other words, for a
|
||||
|
@ -105,11 +101,10 @@ abstract class RenderSliverEdgeInsetsPadding extends RenderSliver with RenderObj
|
|||
assert(resolvedPadding != null);
|
||||
switch (constraints.axis) {
|
||||
case Axis.horizontal:
|
||||
return resolvedPadding.vertical;
|
||||
return resolvedPadding!.vertical;
|
||||
case Axis.vertical:
|
||||
return resolvedPadding.horizontal;
|
||||
return resolvedPadding!.horizontal;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -134,7 +129,7 @@ abstract class RenderSliverEdgeInsetsPadding extends RenderSliver with RenderObj
|
|||
);
|
||||
return;
|
||||
}
|
||||
child.layout(
|
||||
child!.layout(
|
||||
constraints.copyWith(
|
||||
scrollOffset: math.max(0.0, constraints.scrollOffset - beforePadding),
|
||||
cacheOrigin: math.min(0.0, constraints.cacheOrigin + beforePadding),
|
||||
|
@ -146,7 +141,7 @@ abstract class RenderSliverEdgeInsetsPadding extends RenderSliver with RenderObj
|
|||
),
|
||||
parentUsesSize: true,
|
||||
);
|
||||
final SliverGeometry childLayoutGeometry = child.geometry;
|
||||
final SliverGeometry childLayoutGeometry = child!.geometry!;
|
||||
if (childLayoutGeometry.scrollOffsetCorrection != null) {
|
||||
geometry = SliverGeometry(
|
||||
scrollOffsetCorrection: childLayoutGeometry.scrollOffsetCorrection,
|
||||
|
@ -192,21 +187,21 @@ abstract class RenderSliverEdgeInsetsPadding extends RenderSliver with RenderObj
|
|||
hasVisualOverflow: childLayoutGeometry.hasVisualOverflow,
|
||||
);
|
||||
|
||||
final SliverPhysicalParentData childParentData = child.parentData as SliverPhysicalParentData;
|
||||
final SliverPhysicalParentData childParentData = child!.parentData as SliverPhysicalParentData;
|
||||
assert(constraints.axisDirection != null);
|
||||
assert(constraints.growthDirection != null);
|
||||
switch (applyGrowthDirectionToAxisDirection(constraints.axisDirection, constraints.growthDirection)) {
|
||||
case AxisDirection.up:
|
||||
childParentData.paintOffset = Offset(resolvedPadding.left, calculatePaintOffset(constraints, from: resolvedPadding.bottom + childLayoutGeometry.scrollExtent, to: resolvedPadding.bottom + childLayoutGeometry.scrollExtent + resolvedPadding.top));
|
||||
childParentData.paintOffset = Offset(resolvedPadding!.left, calculatePaintOffset(constraints, from: resolvedPadding!.bottom + childLayoutGeometry.scrollExtent, to: resolvedPadding!.bottom + childLayoutGeometry.scrollExtent + resolvedPadding!.top));
|
||||
break;
|
||||
case AxisDirection.right:
|
||||
childParentData.paintOffset = Offset(calculatePaintOffset(constraints, from: 0.0, to: resolvedPadding.left), resolvedPadding.top);
|
||||
childParentData.paintOffset = Offset(calculatePaintOffset(constraints, from: 0.0, to: resolvedPadding!.left), resolvedPadding!.top);
|
||||
break;
|
||||
case AxisDirection.down:
|
||||
childParentData.paintOffset = Offset(resolvedPadding.left, calculatePaintOffset(constraints, from: 0.0, to: resolvedPadding.top));
|
||||
childParentData.paintOffset = Offset(resolvedPadding!.left, calculatePaintOffset(constraints, from: 0.0, to: resolvedPadding!.top));
|
||||
break;
|
||||
case AxisDirection.left:
|
||||
childParentData.paintOffset = Offset(calculatePaintOffset(constraints, from: resolvedPadding.right + childLayoutGeometry.scrollExtent, to: resolvedPadding.right + childLayoutGeometry.scrollExtent + resolvedPadding.left), resolvedPadding.top);
|
||||
childParentData.paintOffset = Offset(calculatePaintOffset(constraints, from: resolvedPadding!.right + childLayoutGeometry.scrollExtent, to: resolvedPadding!.right + childLayoutGeometry.scrollExtent + resolvedPadding!.left), resolvedPadding!.top);
|
||||
break;
|
||||
}
|
||||
assert(childParentData.paintOffset != null);
|
||||
|
@ -217,16 +212,16 @@ abstract class RenderSliverEdgeInsetsPadding extends RenderSliver with RenderObj
|
|||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(SliverHitTestResult result, { @required double mainAxisPosition, @required double crossAxisPosition }) {
|
||||
if (child != null && child.geometry.hitTestExtent > 0.0) {
|
||||
final SliverPhysicalParentData childParentData = child.parentData as SliverPhysicalParentData;
|
||||
bool hitTestChildren(SliverHitTestResult result, { required double mainAxisPosition, required double crossAxisPosition }) {
|
||||
if (child != null && child!.geometry!.hitTestExtent > 0.0) {
|
||||
final SliverPhysicalParentData childParentData = child!.parentData as SliverPhysicalParentData;
|
||||
result.addWithAxisOffset(
|
||||
mainAxisPosition: mainAxisPosition,
|
||||
crossAxisPosition: crossAxisPosition,
|
||||
mainAxisOffset: childMainAxisPosition(child),
|
||||
crossAxisOffset: childCrossAxisPosition(child),
|
||||
mainAxisOffset: childMainAxisPosition(child!),
|
||||
crossAxisOffset: childCrossAxisPosition(child!),
|
||||
paintOffset: childParentData.paintOffset,
|
||||
hitTest: child.hitTest,
|
||||
hitTest: child!.hitTest,
|
||||
);
|
||||
}
|
||||
return false;
|
||||
|
@ -250,16 +245,15 @@ abstract class RenderSliverEdgeInsetsPadding extends RenderSliver with RenderObj
|
|||
switch (applyGrowthDirectionToAxisDirection(constraints.axisDirection, constraints.growthDirection)) {
|
||||
case AxisDirection.up:
|
||||
case AxisDirection.down:
|
||||
return resolvedPadding.left;
|
||||
return resolvedPadding!.left;
|
||||
case AxisDirection.left:
|
||||
case AxisDirection.right:
|
||||
return resolvedPadding.top;
|
||||
return resolvedPadding!.top;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
double childScrollOffset(RenderObject child) {
|
||||
double? childScrollOffset(RenderObject child) {
|
||||
assert(child.parent == this);
|
||||
return beforePadding;
|
||||
}
|
||||
|
@ -274,9 +268,9 @@ abstract class RenderSliverEdgeInsetsPadding extends RenderSliver with RenderObj
|
|||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
if (child != null && child.geometry.visible) {
|
||||
final SliverPhysicalParentData childParentData = child.parentData as SliverPhysicalParentData;
|
||||
context.paintChild(child, offset + childParentData.paintOffset);
|
||||
if (child != null && child!.geometry!.visible) {
|
||||
final SliverPhysicalParentData childParentData = child!.parentData as SliverPhysicalParentData;
|
||||
context.paintChild(child!, offset + childParentData.paintOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,10 +282,10 @@ abstract class RenderSliverEdgeInsetsPadding extends RenderSliver with RenderObj
|
|||
final Size parentSize = getAbsoluteSize();
|
||||
final Rect outerRect = offset & parentSize;
|
||||
Size childSize;
|
||||
Rect innerRect;
|
||||
Rect? innerRect;
|
||||
if (child != null) {
|
||||
childSize = child.getAbsoluteSize();
|
||||
final SliverPhysicalParentData childParentData = child.parentData as SliverPhysicalParentData;
|
||||
childSize = child!.getAbsoluteSize();
|
||||
final SliverPhysicalParentData childParentData = child!.parentData as SliverPhysicalParentData;
|
||||
innerRect = (offset + childParentData.paintOffset) & childSize;
|
||||
assert(innerRect.top >= outerRect.top);
|
||||
assert(innerRect.left >= outerRect.left);
|
||||
|
@ -317,9 +311,9 @@ class RenderSliverPadding extends RenderSliverEdgeInsetsPadding {
|
|||
///
|
||||
/// The [padding] argument must not be null and must have non-negative insets.
|
||||
RenderSliverPadding({
|
||||
@required EdgeInsetsGeometry padding,
|
||||
TextDirection textDirection,
|
||||
RenderSliver child,
|
||||
required EdgeInsetsGeometry padding,
|
||||
TextDirection? textDirection,
|
||||
RenderSliver? child,
|
||||
}) : assert(padding != null),
|
||||
assert(padding.isNonNegative),
|
||||
_padding = padding,
|
||||
|
@ -328,14 +322,14 @@ class RenderSliverPadding extends RenderSliverEdgeInsetsPadding {
|
|||
}
|
||||
|
||||
@override
|
||||
EdgeInsets get resolvedPadding => _resolvedPadding;
|
||||
EdgeInsets _resolvedPadding;
|
||||
EdgeInsets? get resolvedPadding => _resolvedPadding;
|
||||
EdgeInsets? _resolvedPadding;
|
||||
|
||||
void _resolve() {
|
||||
if (resolvedPadding != null)
|
||||
return;
|
||||
_resolvedPadding = padding.resolve(textDirection);
|
||||
assert(resolvedPadding.isNonNegative);
|
||||
assert(resolvedPadding!.isNonNegative);
|
||||
}
|
||||
|
||||
void _markNeedsResolution() {
|
||||
|
@ -362,9 +356,9 @@ class RenderSliverPadding extends RenderSliverEdgeInsetsPadding {
|
|||
///
|
||||
/// This may be changed to null, but only after the [padding] has been changed
|
||||
/// to a value that does not depend on the direction.
|
||||
TextDirection get textDirection => _textDirection;
|
||||
TextDirection _textDirection;
|
||||
set textDirection(TextDirection value) {
|
||||
TextDirection? get textDirection => _textDirection;
|
||||
TextDirection? _textDirection;
|
||||
set textDirection(TextDirection? value) {
|
||||
if (_textDirection == value)
|
||||
return;
|
||||
_textDirection = value;
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/animation.dart';
|
||||
|
@ -38,7 +36,7 @@ class OverScrollHeaderStretchConfiguration {
|
|||
|
||||
/// The callback function to be executed when a user over-scrolls to the
|
||||
/// offset specified by [stretchTriggerOffset].
|
||||
final AsyncCallback onStretchTrigger;
|
||||
final AsyncCallback? onStretchTrigger;
|
||||
}
|
||||
|
||||
/// A base class for slivers that have a [RenderBox] child which scrolls
|
||||
|
@ -63,13 +61,13 @@ abstract class RenderSliverPersistentHeader extends RenderSliver with RenderObje
|
|||
///
|
||||
/// This is an abstract class; this constructor only initializes the [child].
|
||||
RenderSliverPersistentHeader({
|
||||
RenderBox child,
|
||||
RenderBox? child,
|
||||
this.stretchConfiguration,
|
||||
}) {
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
double _lastStretchOffset;
|
||||
late double _lastStretchOffset;
|
||||
|
||||
/// The biggest that this render object can become, in the main axis direction.
|
||||
///
|
||||
|
@ -90,15 +88,14 @@ abstract class RenderSliverPersistentHeader extends RenderSliver with RenderObje
|
|||
double get childExtent {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
assert(child.hasSize);
|
||||
assert(child!.hasSize);
|
||||
assert(constraints.axis != null);
|
||||
switch (constraints.axis) {
|
||||
case Axis.vertical:
|
||||
return child.size.height;
|
||||
return child!.size.height;
|
||||
case Axis.horizontal:
|
||||
return child.size.width;
|
||||
return child!.size.width;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool _needsUpdateChild = true;
|
||||
|
@ -114,7 +111,7 @@ abstract class RenderSliverPersistentHeader extends RenderSliver with RenderObje
|
|||
///
|
||||
/// * [SliverAppBar], which creates a header that can stretched into an
|
||||
/// overscroll area and trigger a callback function.
|
||||
OverScrollHeaderStretchConfiguration stretchConfiguration;
|
||||
OverScrollHeaderStretchConfiguration? stretchConfiguration;
|
||||
|
||||
/// Update the child render object if necessary.
|
||||
///
|
||||
|
@ -179,8 +176,9 @@ abstract class RenderSliverPersistentHeader extends RenderSliver with RenderObje
|
|||
]);
|
||||
}());
|
||||
double stretchOffset = 0.0;
|
||||
if (stretchConfiguration != null && childMainAxisPosition(child) == 0.0)
|
||||
if (stretchConfiguration != null && constraints.scrollOffset == 0.0) {
|
||||
stretchOffset += constraints.overlap.abs();
|
||||
}
|
||||
|
||||
child?.layout(
|
||||
constraints.asBoxConstraints(
|
||||
|
@ -190,10 +188,10 @@ abstract class RenderSliverPersistentHeader extends RenderSliver with RenderObje
|
|||
);
|
||||
|
||||
if (stretchConfiguration != null &&
|
||||
stretchConfiguration.onStretchTrigger != null &&
|
||||
stretchOffset >= stretchConfiguration.stretchTriggerOffset &&
|
||||
_lastStretchOffset <= stretchConfiguration.stretchTriggerOffset) {
|
||||
stretchConfiguration.onStretchTrigger();
|
||||
stretchConfiguration!.onStretchTrigger != null &&
|
||||
stretchOffset >= stretchConfiguration!.stretchTriggerOffset &&
|
||||
_lastStretchOffset <= stretchConfiguration!.stretchTriggerOffset) {
|
||||
stretchConfiguration!.onStretchTrigger!();
|
||||
}
|
||||
_lastStretchOffset = stretchOffset;
|
||||
}
|
||||
|
@ -222,10 +220,10 @@ abstract class RenderSliverPersistentHeader extends RenderSliver with RenderObje
|
|||
double childMainAxisPosition(covariant RenderObject child) => super.childMainAxisPosition(child);
|
||||
|
||||
@override
|
||||
bool hitTestChildren(SliverHitTestResult result, { @required double mainAxisPosition, @required double crossAxisPosition }) {
|
||||
assert(geometry.hitTestExtent > 0.0);
|
||||
bool hitTestChildren(SliverHitTestResult result, { required double mainAxisPosition, required double crossAxisPosition }) {
|
||||
assert(geometry!.hitTestExtent > 0.0);
|
||||
if (child != null)
|
||||
return hitTestBoxChild(BoxHitTestResult.wrap(result), child, mainAxisPosition: mainAxisPosition, crossAxisPosition: crossAxisPosition);
|
||||
return hitTestBoxChild(BoxHitTestResult.wrap(result), child!, mainAxisPosition: mainAxisPosition, crossAxisPosition: crossAxisPosition);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -238,23 +236,23 @@ abstract class RenderSliverPersistentHeader extends RenderSliver with RenderObje
|
|||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
if (child != null && geometry.visible) {
|
||||
if (child != null && geometry!.visible) {
|
||||
assert(constraints.axisDirection != null);
|
||||
switch (applyGrowthDirectionToAxisDirection(constraints.axisDirection, constraints.growthDirection)) {
|
||||
case AxisDirection.up:
|
||||
offset += Offset(0.0, geometry.paintExtent - childMainAxisPosition(child) - childExtent);
|
||||
offset += Offset(0.0, geometry!.paintExtent - childMainAxisPosition(child!) - childExtent);
|
||||
break;
|
||||
case AxisDirection.down:
|
||||
offset += Offset(0.0, childMainAxisPosition(child));
|
||||
offset += Offset(0.0, childMainAxisPosition(child!));
|
||||
break;
|
||||
case AxisDirection.left:
|
||||
offset += Offset(geometry.paintExtent - childMainAxisPosition(child) - childExtent, 0.0);
|
||||
offset += Offset(geometry!.paintExtent - childMainAxisPosition(child!) - childExtent, 0.0);
|
||||
break;
|
||||
case AxisDirection.right:
|
||||
offset += Offset(childMainAxisPosition(child), 0.0);
|
||||
offset += Offset(childMainAxisPosition(child!), 0.0);
|
||||
break;
|
||||
}
|
||||
context.paintChild(child, offset);
|
||||
context.paintChild(child!, offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,7 +266,7 @@ abstract class RenderSliverPersistentHeader extends RenderSliver with RenderObje
|
|||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(DoubleProperty.lazy('maxExtent', () => maxExtent));
|
||||
properties.add(DoubleProperty.lazy('child position', () => childMainAxisPosition(child)));
|
||||
properties.add(DoubleProperty.lazy('child position', () => childMainAxisPosition(child!)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,8 +279,8 @@ abstract class RenderSliverScrollingPersistentHeader extends RenderSliverPersist
|
|||
/// Creates a sliver that shrinks when it hits the start of the viewport, then
|
||||
/// scrolls off.
|
||||
RenderSliverScrollingPersistentHeader({
|
||||
RenderBox child,
|
||||
OverScrollHeaderStretchConfiguration stretchConfiguration,
|
||||
RenderBox? child,
|
||||
OverScrollHeaderStretchConfiguration? stretchConfiguration,
|
||||
}) : super(
|
||||
child: child,
|
||||
stretchConfiguration: stretchConfiguration,
|
||||
|
@ -290,7 +288,7 @@ abstract class RenderSliverScrollingPersistentHeader extends RenderSliverPersist
|
|||
|
||||
// Distance from our leading edge to the child's leading edge, in the axis
|
||||
// direction. Negative if we're scrolled off the top.
|
||||
double _childPosition;
|
||||
double? _childPosition;
|
||||
|
||||
/// Updates [geometry], and returns the new value for [childMainAxisPosition].
|
||||
///
|
||||
|
@ -306,7 +304,7 @@ abstract class RenderSliverScrollingPersistentHeader extends RenderSliverPersist
|
|||
geometry = SliverGeometry(
|
||||
scrollExtent: maxExtent,
|
||||
paintOrigin: math.min(constraints.overlap, 0.0),
|
||||
paintExtent: paintExtent.clamp(0.0, constraints.remainingPaintExtent) as double,
|
||||
paintExtent: paintExtent.clamp(0.0, constraints.remainingPaintExtent),
|
||||
maxPaintExtent: maxExtent + stretchOffset,
|
||||
hasVisualOverflow: true, // Conservatively say we do have overflow to avoid complexity.
|
||||
);
|
||||
|
@ -323,7 +321,7 @@ abstract class RenderSliverScrollingPersistentHeader extends RenderSliverPersist
|
|||
geometry = SliverGeometry(
|
||||
scrollExtent: maxExtent,
|
||||
paintOrigin: math.min(constraints.overlap, 0.0),
|
||||
paintExtent: paintExtent.clamp(0.0, constraints.remainingPaintExtent) as double,
|
||||
paintExtent: paintExtent.clamp(0.0, constraints.remainingPaintExtent),
|
||||
maxPaintExtent: maxExtent,
|
||||
hasVisualOverflow: true, // Conservatively say we do have overflow to avoid complexity.
|
||||
);
|
||||
|
@ -333,7 +331,8 @@ abstract class RenderSliverScrollingPersistentHeader extends RenderSliverPersist
|
|||
@override
|
||||
double childMainAxisPosition(RenderBox child) {
|
||||
assert(child == this.child);
|
||||
return _childPosition;
|
||||
assert(_childPosition != null);
|
||||
return _childPosition!;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,8 +345,8 @@ abstract class RenderSliverPinnedPersistentHeader extends RenderSliverPersistent
|
|||
/// Creates a sliver that shrinks when it hits the start of the viewport, then
|
||||
/// stays pinned there.
|
||||
RenderSliverPinnedPersistentHeader({
|
||||
RenderBox child,
|
||||
OverScrollHeaderStretchConfiguration stretchConfiguration,
|
||||
RenderBox? child,
|
||||
OverScrollHeaderStretchConfiguration? stretchConfiguration,
|
||||
}) : super(
|
||||
child: child,
|
||||
stretchConfiguration: stretchConfiguration,
|
||||
|
@ -360,7 +359,7 @@ abstract class RenderSliverPinnedPersistentHeader extends RenderSliverPersistent
|
|||
final bool overlapsContent = constraints.overlap > 0.0;
|
||||
layoutChild(constraints.scrollOffset, maxExtent, overlapsContent: overlapsContent);
|
||||
final double effectiveRemainingPaintExtent = math.max(0, constraints.remainingPaintExtent - constraints.overlap);
|
||||
final double layoutExtent = (maxExtent - constraints.scrollOffset).clamp(0.0, effectiveRemainingPaintExtent) as double;
|
||||
final double layoutExtent = (maxExtent - constraints.scrollOffset).clamp(0.0, effectiveRemainingPaintExtent);
|
||||
final double stretchOffset = stretchConfiguration != null ?
|
||||
constraints.overlap.abs() :
|
||||
0.0;
|
||||
|
@ -394,7 +393,7 @@ class FloatingHeaderSnapConfiguration {
|
|||
/// Creates an object that specifies how a floating header is to be "snapped"
|
||||
/// (animated) into or out of view.
|
||||
FloatingHeaderSnapConfiguration({
|
||||
@required this.vsync,
|
||||
required this.vsync,
|
||||
this.curve = Curves.ease,
|
||||
this.duration = const Duration(milliseconds: 300),
|
||||
}) : assert(vsync != null),
|
||||
|
@ -425,23 +424,23 @@ abstract class RenderSliverFloatingPersistentHeader extends RenderSliverPersiste
|
|||
/// scrolls off, and comes back immediately when the user reverses the scroll
|
||||
/// direction.
|
||||
RenderSliverFloatingPersistentHeader({
|
||||
RenderBox child,
|
||||
FloatingHeaderSnapConfiguration snapConfiguration,
|
||||
OverScrollHeaderStretchConfiguration stretchConfiguration,
|
||||
RenderBox? child,
|
||||
FloatingHeaderSnapConfiguration? snapConfiguration,
|
||||
OverScrollHeaderStretchConfiguration? stretchConfiguration,
|
||||
}) : _snapConfiguration = snapConfiguration,
|
||||
super(
|
||||
child: child,
|
||||
stretchConfiguration: stretchConfiguration,
|
||||
);
|
||||
|
||||
AnimationController _controller;
|
||||
Animation<double> _animation;
|
||||
double _lastActualScrollOffset;
|
||||
double _effectiveScrollOffset;
|
||||
AnimationController? _controller;
|
||||
late Animation<double> _animation;
|
||||
double? _lastActualScrollOffset;
|
||||
double? _effectiveScrollOffset;
|
||||
|
||||
// Distance from our leading edge to the child's leading edge, in the axis
|
||||
// direction. Negative if we're scrolled off the top.
|
||||
double _childPosition;
|
||||
double? _childPosition;
|
||||
|
||||
@override
|
||||
void detach() {
|
||||
|
@ -462,16 +461,16 @@ abstract class RenderSliverFloatingPersistentHeader extends RenderSliverPersiste
|
|||
/// start or stop the floating header's animation.
|
||||
/// * [SliverAppBar], which creates a header that can be pinned, floating,
|
||||
/// and snapped into view via the corresponding parameters.
|
||||
FloatingHeaderSnapConfiguration get snapConfiguration => _snapConfiguration;
|
||||
FloatingHeaderSnapConfiguration _snapConfiguration;
|
||||
set snapConfiguration(FloatingHeaderSnapConfiguration value) {
|
||||
FloatingHeaderSnapConfiguration? get snapConfiguration => _snapConfiguration;
|
||||
FloatingHeaderSnapConfiguration? _snapConfiguration;
|
||||
set snapConfiguration(FloatingHeaderSnapConfiguration? value) {
|
||||
if (value == _snapConfiguration)
|
||||
return;
|
||||
if (value == null) {
|
||||
_controller?.dispose();
|
||||
_controller = null;
|
||||
} else {
|
||||
if (_snapConfiguration != null && value.vsync != _snapConfiguration.vsync)
|
||||
if (_snapConfiguration != null && value.vsync != _snapConfiguration!.vsync)
|
||||
_controller?.resync(value.vsync);
|
||||
}
|
||||
_snapConfiguration = value;
|
||||
|
@ -487,13 +486,13 @@ abstract class RenderSliverFloatingPersistentHeader extends RenderSliverPersiste
|
|||
stretchOffset += constraints.overlap.abs();
|
||||
}
|
||||
final double maxExtent = this.maxExtent;
|
||||
final double paintExtent = maxExtent - _effectiveScrollOffset;
|
||||
final double paintExtent = maxExtent - _effectiveScrollOffset!;
|
||||
final double layoutExtent = maxExtent - constraints.scrollOffset;
|
||||
geometry = SliverGeometry(
|
||||
scrollExtent: maxExtent,
|
||||
paintOrigin: math.min(constraints.overlap, 0.0),
|
||||
paintExtent: paintExtent.clamp(0.0, constraints.remainingPaintExtent) as double,
|
||||
layoutExtent: layoutExtent.clamp(0.0, constraints.remainingPaintExtent) as double,
|
||||
paintExtent: paintExtent.clamp(0.0, constraints.remainingPaintExtent),
|
||||
layoutExtent: layoutExtent.clamp(0.0, constraints.remainingPaintExtent),
|
||||
maxPaintExtent: maxExtent + stretchOffset,
|
||||
hasVisualOverflow: true, // Conservatively say we do have overflow to avoid complexity.
|
||||
);
|
||||
|
@ -504,13 +503,13 @@ abstract class RenderSliverFloatingPersistentHeader extends RenderSliverPersiste
|
|||
void maybeStartSnapAnimation(ScrollDirection direction) {
|
||||
if (snapConfiguration == null)
|
||||
return;
|
||||
if (direction == ScrollDirection.forward && _effectiveScrollOffset <= 0.0)
|
||||
if (direction == ScrollDirection.forward && _effectiveScrollOffset! <= 0.0)
|
||||
return;
|
||||
if (direction == ScrollDirection.reverse && _effectiveScrollOffset >= maxExtent)
|
||||
if (direction == ScrollDirection.reverse && _effectiveScrollOffset! >= maxExtent)
|
||||
return;
|
||||
|
||||
final TickerProvider vsync = snapConfiguration.vsync;
|
||||
final Duration duration = snapConfiguration.duration;
|
||||
final TickerProvider vsync = snapConfiguration!.vsync;
|
||||
final Duration duration = snapConfiguration!.duration;
|
||||
_controller ??= AnimationController(vsync: vsync, duration: duration)
|
||||
..addListener(() {
|
||||
if (_effectiveScrollOffset == _animation.value)
|
||||
|
@ -519,16 +518,16 @@ abstract class RenderSliverFloatingPersistentHeader extends RenderSliverPersiste
|
|||
markNeedsLayout();
|
||||
});
|
||||
|
||||
_animation = _controller.drive(
|
||||
_animation = _controller!.drive(
|
||||
Tween<double>(
|
||||
begin: _effectiveScrollOffset,
|
||||
end: direction == ScrollDirection.forward ? 0.0 : maxExtent,
|
||||
).chain(CurveTween(
|
||||
curve: snapConfiguration.curve,
|
||||
curve: snapConfiguration!.curve,
|
||||
)),
|
||||
);
|
||||
|
||||
_controller.forward(from: 0.0);
|
||||
_controller!.forward(from: 0.0);
|
||||
}
|
||||
|
||||
/// If a header snap animation is underway then stop it.
|
||||
|
@ -541,26 +540,26 @@ abstract class RenderSliverFloatingPersistentHeader extends RenderSliverPersiste
|
|||
final SliverConstraints constraints = this.constraints;
|
||||
final double maxExtent = this.maxExtent;
|
||||
if (_lastActualScrollOffset != null && // We've laid out at least once to get an initial position, and either
|
||||
((constraints.scrollOffset < _lastActualScrollOffset) || // we are scrolling back, so should reveal, or
|
||||
(_effectiveScrollOffset < maxExtent))) { // some part of it is visible, so should shrink or reveal as appropriate.
|
||||
double delta = _lastActualScrollOffset - constraints.scrollOffset;
|
||||
((constraints.scrollOffset < _lastActualScrollOffset!) || // we are scrolling back, so should reveal, or
|
||||
(_effectiveScrollOffset! < maxExtent))) { // some part of it is visible, so should shrink or reveal as appropriate.
|
||||
double delta = _lastActualScrollOffset! - constraints.scrollOffset;
|
||||
|
||||
final bool allowFloatingExpansion = constraints.userScrollDirection == ScrollDirection.forward;
|
||||
if (allowFloatingExpansion) {
|
||||
if (_effectiveScrollOffset > maxExtent) // We're scrolled off-screen, but should reveal, so
|
||||
if (_effectiveScrollOffset! > maxExtent) // We're scrolled off-screen, but should reveal, so
|
||||
_effectiveScrollOffset = maxExtent; // pretend we're just at the limit.
|
||||
} else {
|
||||
if (delta > 0.0) // If we are trying to expand when allowFloatingExpansion is false,
|
||||
delta = 0.0; // disallow the expansion. (But allow shrinking, i.e. delta < 0.0 is fine.)
|
||||
}
|
||||
_effectiveScrollOffset = (_effectiveScrollOffset - delta).clamp(0.0, constraints.scrollOffset) as double;
|
||||
_effectiveScrollOffset = (_effectiveScrollOffset! - delta).clamp(0.0, constraints.scrollOffset);
|
||||
} else {
|
||||
_effectiveScrollOffset = constraints.scrollOffset;
|
||||
}
|
||||
final bool overlapsContent = _effectiveScrollOffset < constraints.scrollOffset;
|
||||
final bool overlapsContent = _effectiveScrollOffset! < constraints.scrollOffset;
|
||||
|
||||
layoutChild(
|
||||
_effectiveScrollOffset,
|
||||
_effectiveScrollOffset!,
|
||||
maxExtent,
|
||||
overlapsContent: overlapsContent,
|
||||
);
|
||||
|
@ -571,7 +570,7 @@ abstract class RenderSliverFloatingPersistentHeader extends RenderSliverPersiste
|
|||
@override
|
||||
double childMainAxisPosition(RenderBox child) {
|
||||
assert(child == this.child);
|
||||
return _childPosition;
|
||||
return _childPosition ?? 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -594,9 +593,9 @@ abstract class RenderSliverFloatingPinnedPersistentHeader extends RenderSliverFl
|
|||
/// stays pinned there, and grows immediately when the user reverses the
|
||||
/// scroll direction.
|
||||
RenderSliverFloatingPinnedPersistentHeader({
|
||||
RenderBox child,
|
||||
FloatingHeaderSnapConfiguration snapConfiguration,
|
||||
OverScrollHeaderStretchConfiguration stretchConfiguration,
|
||||
RenderBox? child,
|
||||
FloatingHeaderSnapConfiguration? snapConfiguration,
|
||||
OverScrollHeaderStretchConfiguration? stretchConfiguration,
|
||||
}) : super(
|
||||
child: child,
|
||||
snapConfiguration: snapConfiguration,
|
||||
|
@ -610,11 +609,11 @@ abstract class RenderSliverFloatingPinnedPersistentHeader extends RenderSliverFl
|
|||
minExtent :
|
||||
constraints.remainingPaintExtent;
|
||||
final double maxExtent = this.maxExtent;
|
||||
final double paintExtent = maxExtent - _effectiveScrollOffset;
|
||||
final double paintExtent = maxExtent - _effectiveScrollOffset!;
|
||||
final double clampedPaintExtent = paintExtent.clamp(
|
||||
minAllowedExtent,
|
||||
constraints.remainingPaintExtent,
|
||||
) as double;
|
||||
);
|
||||
final double layoutExtent = maxExtent - constraints.scrollOffset;
|
||||
final double stretchOffset = stretchConfiguration != null ?
|
||||
constraints.overlap.abs() :
|
||||
|
@ -623,7 +622,7 @@ abstract class RenderSliverFloatingPinnedPersistentHeader extends RenderSliverFl
|
|||
scrollExtent: maxExtent,
|
||||
paintOrigin: math.min(constraints.overlap, 0.0),
|
||||
paintExtent: clampedPaintExtent,
|
||||
layoutExtent: layoutExtent.clamp(0.0, clampedPaintExtent) as double,
|
||||
layoutExtent: layoutExtent.clamp(0.0, clampedPaintExtent),
|
||||
maxPaintExtent: maxExtent + stretchOffset,
|
||||
maxScrollObstructionExtent: minExtent,
|
||||
hasVisualOverflow: true, // Conservatively say we do have overflow to avoid complexity.
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui' show lerpDouble, hashValues;
|
||||
|
||||
|
@ -62,22 +60,22 @@ class RelativeRect {
|
|||
/// Distance from the left side of the container to the left side of this rectangle.
|
||||
///
|
||||
/// May be negative if the left side of the rectangle is outside of the container.
|
||||
final double/*!*/ left;
|
||||
final double left;
|
||||
|
||||
/// Distance from the top side of the container to the top side of this rectangle.
|
||||
///
|
||||
/// May be negative if the top side of the rectangle is outside of the container.
|
||||
final double/*!*/ top;
|
||||
final double top;
|
||||
|
||||
/// Distance from the right side of the container to the right side of this rectangle.
|
||||
///
|
||||
/// May be positive if the right side of the rectangle is outside of the container.
|
||||
final double/*!*/ right;
|
||||
final double right;
|
||||
|
||||
/// Distance from the bottom side of the container to the bottom side of this rectangle.
|
||||
///
|
||||
/// May be positive if the bottom side of the rectangle is outside of the container.
|
||||
final double/*!*/ bottom;
|
||||
final double bottom;
|
||||
|
||||
/// Returns whether any of the values are greater than zero.
|
||||
///
|
||||
|
@ -134,21 +132,21 @@ class RelativeRect {
|
|||
/// If either rect is null, this function interpolates from [RelativeRect.fill].
|
||||
///
|
||||
/// {@macro dart.ui.shadow.lerp}
|
||||
static RelativeRect lerp(RelativeRect/*?*/ a, RelativeRect/*?*/ b, double t) {
|
||||
static RelativeRect? lerp(RelativeRect? a, RelativeRect? b, double t) {
|
||||
assert(t != null);
|
||||
if (a == null && b == null)
|
||||
return null;
|
||||
if (a == null)
|
||||
return RelativeRect.fromLTRB(b.left * t, b.top * t, b.right * t, b.bottom * t);
|
||||
return RelativeRect.fromLTRB(b!.left * t, b.top * t, b.right * t, b.bottom * t);
|
||||
if (b == null) {
|
||||
final double k = 1.0 - t;
|
||||
return RelativeRect.fromLTRB(b.left * k, b.top * k, b.right * k, b.bottom * k);
|
||||
return RelativeRect.fromLTRB(b!.left * k, b.top * k, b.right * k, b.bottom * k);
|
||||
}
|
||||
return RelativeRect.fromLTRB(
|
||||
lerpDouble(a.left, b.left, t),
|
||||
lerpDouble(a.top, b.top, t),
|
||||
lerpDouble(a.right, b.right, t),
|
||||
lerpDouble(a.bottom, b.bottom, t),
|
||||
lerpDouble(a.left, b.left, t)!,
|
||||
lerpDouble(a.top, b.top, t)!,
|
||||
lerpDouble(a.right, b.right, t)!,
|
||||
lerpDouble(a.bottom, b.bottom, t)!,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -167,35 +165,35 @@ class RelativeRect {
|
|||
int get hashCode => hashValues(left, top, right, bottom);
|
||||
|
||||
@override
|
||||
String toString() => 'RelativeRect.fromLTRB(${left?.toStringAsFixed(1)}, ${top?.toStringAsFixed(1)}, ${right?.toStringAsFixed(1)}, ${bottom?.toStringAsFixed(1)})';
|
||||
String toString() => 'RelativeRect.fromLTRB(${left.toStringAsFixed(1)}, ${top.toStringAsFixed(1)}, ${right.toStringAsFixed(1)}, ${bottom.toStringAsFixed(1)})';
|
||||
}
|
||||
|
||||
/// Parent data for use with [RenderStack].
|
||||
class StackParentData extends ContainerBoxParentData<RenderBox> {
|
||||
/// The distance by which the child's top edge is inset from the top of the stack.
|
||||
double top;
|
||||
double? top;
|
||||
|
||||
/// The distance by which the child's right edge is inset from the right of the stack.
|
||||
double right;
|
||||
double? right;
|
||||
|
||||
/// The distance by which the child's bottom edge is inset from the bottom of the stack.
|
||||
double bottom;
|
||||
double? bottom;
|
||||
|
||||
/// The distance by which the child's left edge is inset from the left of the stack.
|
||||
double left;
|
||||
double? left;
|
||||
|
||||
/// The child's width.
|
||||
///
|
||||
/// Ignored if both left and right are non-null.
|
||||
double width;
|
||||
double? width;
|
||||
|
||||
/// The child's height.
|
||||
///
|
||||
/// Ignored if both top and bottom are non-null.
|
||||
double height;
|
||||
double? height;
|
||||
|
||||
/// Get or set the current values in terms of a RelativeRect object.
|
||||
RelativeRect get rect => RelativeRect.fromLTRB(left, top, right, bottom);
|
||||
RelativeRect get rect => RelativeRect.fromLTRB(left!, top!, right!, bottom!);
|
||||
set rect(RelativeRect value) {
|
||||
top = value.top;
|
||||
right = value.right;
|
||||
|
@ -328,9 +326,9 @@ class RenderStack extends RenderBox
|
|||
/// By default, the non-positioned children of the stack are aligned by their
|
||||
/// top left corners.
|
||||
RenderStack({
|
||||
List<RenderBox> children,
|
||||
List<RenderBox>? children,
|
||||
AlignmentGeometry alignment = AlignmentDirectional.topStart,
|
||||
TextDirection textDirection,
|
||||
TextDirection? textDirection,
|
||||
StackFit fit = StackFit.loose,
|
||||
Clip clipBehavior = Clip.hardEdge,
|
||||
}) : assert(alignment != null),
|
||||
|
@ -351,7 +349,7 @@ class RenderStack extends RenderBox
|
|||
child.parentData = StackParentData();
|
||||
}
|
||||
|
||||
Alignment _resolvedAlignment;
|
||||
Alignment? _resolvedAlignment;
|
||||
|
||||
void _resolve() {
|
||||
if (_resolvedAlignment != null)
|
||||
|
@ -393,9 +391,9 @@ class RenderStack extends RenderBox
|
|||
///
|
||||
/// This may be changed to null, but only after the [alignment] has been changed
|
||||
/// to a value that does not depend on the direction.
|
||||
TextDirection get textDirection => _textDirection;
|
||||
TextDirection _textDirection;
|
||||
set textDirection(TextDirection value) {
|
||||
TextDirection? get textDirection => _textDirection;
|
||||
TextDirection? _textDirection;
|
||||
set textDirection(TextDirection? value) {
|
||||
if (_textDirection == value)
|
||||
return;
|
||||
_textDirection = value;
|
||||
|
@ -432,9 +430,9 @@ class RenderStack extends RenderBox
|
|||
}
|
||||
|
||||
/// Helper function for calculating the intrinsics metrics of a Stack.
|
||||
static double getIntrinsicDimension(RenderBox firstChild, double mainChildSizeGetter(RenderBox child)) {
|
||||
static double getIntrinsicDimension(RenderBox? firstChild, double mainChildSizeGetter(RenderBox child)) {
|
||||
double extent = 0.0;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
final StackParentData childParentData = child.parentData as StackParentData;
|
||||
if (!childParentData.isPositioned)
|
||||
|
@ -466,7 +464,7 @@ class RenderStack extends RenderBox
|
|||
}
|
||||
|
||||
@override
|
||||
double computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
double? computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
return defaultComputeDistanceToHighestActualBaseline(baseline);
|
||||
}
|
||||
|
||||
|
@ -481,23 +479,22 @@ class RenderStack extends RenderBox
|
|||
BoxConstraints childConstraints = const BoxConstraints();
|
||||
|
||||
if (childParentData.left != null && childParentData.right != null)
|
||||
childConstraints = childConstraints.tighten(width: size.width - childParentData.right - childParentData.left);
|
||||
childConstraints = childConstraints.tighten(width: size.width - childParentData.right! - childParentData.left!);
|
||||
else if (childParentData.width != null)
|
||||
childConstraints = childConstraints.tighten(width: childParentData.width);
|
||||
|
||||
if (childParentData.top != null && childParentData.bottom != null)
|
||||
childConstraints = childConstraints.tighten(height: size.height - childParentData.bottom - childParentData.top);
|
||||
childConstraints = childConstraints.tighten(height: size.height - childParentData.bottom! - childParentData.top!);
|
||||
else if (childParentData.height != null)
|
||||
childConstraints = childConstraints.tighten(height: childParentData.height);
|
||||
|
||||
child.layout(childConstraints, parentUsesSize: true);
|
||||
|
||||
// TODO(ianh): x should be late final
|
||||
/*late*/ double/*!*/ x;
|
||||
late final double x;
|
||||
if (childParentData.left != null) {
|
||||
x = childParentData.left;
|
||||
x = childParentData.left!;
|
||||
} else if (childParentData.right != null) {
|
||||
x = size.width - childParentData.right - child.size.width;
|
||||
x = size.width - childParentData.right! - child.size.width;
|
||||
} else {
|
||||
x = alignment.alongOffset(size - child.size as Offset).dx;
|
||||
}
|
||||
|
@ -505,12 +502,11 @@ class RenderStack extends RenderBox
|
|||
if (x < 0.0 || x + child.size.width > size.width)
|
||||
hasVisualOverflow = true;
|
||||
|
||||
// TODO(ianh): y should be late final
|
||||
/*late*/ double/*!*/ y;
|
||||
late final double y;
|
||||
if (childParentData.top != null) {
|
||||
y = childParentData.top;
|
||||
y = childParentData.top!;
|
||||
} else if (childParentData.bottom != null) {
|
||||
y = size.height - childParentData.bottom - child.size.height;
|
||||
y = size.height - childParentData.bottom! - child.size.height;
|
||||
} else {
|
||||
y = alignment.alongOffset(size - child.size as Offset).dy;
|
||||
}
|
||||
|
@ -554,7 +550,7 @@ class RenderStack extends RenderBox
|
|||
}
|
||||
assert(nonPositionedConstraints != null);
|
||||
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
final StackParentData childParentData = child.parentData as StackParentData;
|
||||
|
||||
|
@ -586,9 +582,9 @@ class RenderStack extends RenderBox
|
|||
final StackParentData childParentData = child.parentData as StackParentData;
|
||||
|
||||
if (!childParentData.isPositioned) {
|
||||
childParentData.offset = _resolvedAlignment.alongOffset(size - child.size as Offset);
|
||||
childParentData.offset = _resolvedAlignment!.alongOffset(size - child.size as Offset);
|
||||
} else {
|
||||
_hasVisualOverflow = layoutPositionedChild(child, childParentData, size, _resolvedAlignment) || _hasVisualOverflow;
|
||||
_hasVisualOverflow = layoutPositionedChild(child, childParentData, size, _resolvedAlignment!) || _hasVisualOverflow;
|
||||
}
|
||||
|
||||
assert(child.parentData == childParentData);
|
||||
|
@ -597,7 +593,7 @@ class RenderStack extends RenderBox
|
|||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
|
||||
return defaultHitTestChildren(result, position: position);
|
||||
}
|
||||
|
||||
|
@ -620,7 +616,7 @@ class RenderStack extends RenderBox
|
|||
}
|
||||
|
||||
@override
|
||||
Rect describeApproximatePaintClip(RenderObject child) => _hasVisualOverflow ? Offset.zero & size : null;
|
||||
Rect? describeApproximatePaintClip(RenderObject child) => _hasVisualOverflow ? Offset.zero & size : null;
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
|
@ -642,10 +638,10 @@ class RenderIndexedStack extends RenderStack {
|
|||
///
|
||||
/// If the [index] parameter is null, nothing is displayed.
|
||||
RenderIndexedStack({
|
||||
List<RenderBox> children,
|
||||
List<RenderBox>? children,
|
||||
AlignmentGeometry alignment = AlignmentDirectional.topStart,
|
||||
TextDirection textDirection,
|
||||
int index = 0,
|
||||
TextDirection? textDirection,
|
||||
int? index = 0,
|
||||
}) : _index = index,
|
||||
super(
|
||||
children: children,
|
||||
|
@ -660,9 +656,9 @@ class RenderIndexedStack extends RenderStack {
|
|||
}
|
||||
|
||||
/// The index of the child to show, null if nothing is to be displayed.
|
||||
int get index => _index;
|
||||
int _index;
|
||||
set index(int value) {
|
||||
int? get index => _index;
|
||||
int? _index;
|
||||
set index(int? value) {
|
||||
if (_index != value) {
|
||||
_index = value;
|
||||
markNeedsLayout();
|
||||
|
@ -671,20 +667,20 @@ class RenderIndexedStack extends RenderStack {
|
|||
|
||||
RenderBox _childAtIndex() {
|
||||
assert(index != null);
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
int i = 0;
|
||||
while (child != null && i < index) {
|
||||
while (child != null && i < index!) {
|
||||
final StackParentData childParentData = child.parentData as StackParentData;
|
||||
child = childParentData.nextSibling;
|
||||
i += 1;
|
||||
}
|
||||
assert(i == index);
|
||||
assert(child != null);
|
||||
return child;
|
||||
return child!;
|
||||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, { @required Offset position }) {
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
|
||||
if (firstChild == null || index == null)
|
||||
return false;
|
||||
assert(position != null);
|
||||
|
@ -693,9 +689,9 @@ class RenderIndexedStack extends RenderStack {
|
|||
return result.addWithPaintOffset(
|
||||
offset: childParentData.offset,
|
||||
position: position,
|
||||
hitTest: (BoxHitTestResult result, Offset transformed) {
|
||||
hitTest: (BoxHitTestResult result, Offset? transformed) {
|
||||
assert(transformed == position - childParentData.offset);
|
||||
return child.hitTest(result, position: transformed);
|
||||
return child.hitTest(result, position: transformed!);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:collection';
|
||||
import 'dart:math' as math;
|
||||
|
||||
|
@ -16,13 +14,13 @@ import 'table_border.dart';
|
|||
/// Parent data used by [RenderTable] for its children.
|
||||
class TableCellParentData extends BoxParentData {
|
||||
/// Where this cell should be placed vertically.
|
||||
TableCellVerticalAlignment verticalAlignment;
|
||||
TableCellVerticalAlignment? verticalAlignment;
|
||||
|
||||
/// The column that the child was in the last time it was laid out.
|
||||
int x;
|
||||
int? x;
|
||||
|
||||
/// The row that the child was in the last time it was laid out.
|
||||
int y;
|
||||
int? y;
|
||||
|
||||
@override
|
||||
String toString() => '${super.toString()}; ${verticalAlignment == null ? "default vertical alignment" : "$verticalAlignment"}';
|
||||
|
@ -75,7 +73,7 @@ abstract class TableColumnWidth {
|
|||
/// The `cells` argument is an iterable that provides all the cells
|
||||
/// in the table for this column. Walking the cells is by definition
|
||||
/// O(N), so algorithms that do that should be considered expensive.
|
||||
double flex(Iterable<RenderBox> cells) => null;
|
||||
double? flex(Iterable<RenderBox> cells) => null;
|
||||
|
||||
@override
|
||||
String toString() => objectRuntimeType(this, 'TableColumnWidth');
|
||||
|
@ -98,7 +96,7 @@ class IntrinsicColumnWidth extends TableColumnWidth {
|
|||
/// there is any room left over when laying out the table. If `flex` is
|
||||
/// null (the default), the table will not distribute any extra space to the
|
||||
/// column.
|
||||
const IntrinsicColumnWidth({ double flex }) : _flex = flex;
|
||||
const IntrinsicColumnWidth({ double? flex }) : _flex = flex;
|
||||
|
||||
@override
|
||||
double minIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
|
||||
|
@ -116,10 +114,10 @@ class IntrinsicColumnWidth extends TableColumnWidth {
|
|||
return result;
|
||||
}
|
||||
|
||||
final double _flex;
|
||||
final double? _flex;
|
||||
|
||||
@override
|
||||
double flex(Iterable<RenderBox> cells) => _flex;
|
||||
double? flex(Iterable<RenderBox> cells) => _flex;
|
||||
|
||||
@override
|
||||
String toString() => '${objectRuntimeType(this, 'IntrinsicColumnWidth')}(flex: ${_flex?.toStringAsFixed(1)})';
|
||||
|
@ -257,11 +255,11 @@ class MaxColumnWidth extends TableColumnWidth {
|
|||
}
|
||||
|
||||
@override
|
||||
double flex(Iterable<RenderBox> cells) {
|
||||
final double aFlex = a.flex(cells);
|
||||
double? flex(Iterable<RenderBox> cells) {
|
||||
final double? aFlex = a.flex(cells);
|
||||
if (aFlex == null)
|
||||
return b.flex(cells);
|
||||
final double bFlex = b.flex(cells);
|
||||
final double? bFlex = b.flex(cells);
|
||||
if (bFlex == null)
|
||||
return null;
|
||||
return math.max(aFlex, bFlex);
|
||||
|
@ -308,11 +306,11 @@ class MinColumnWidth extends TableColumnWidth {
|
|||
}
|
||||
|
||||
@override
|
||||
double flex(Iterable<RenderBox> cells) {
|
||||
final double aFlex = a.flex(cells);
|
||||
double? flex(Iterable<RenderBox> cells) {
|
||||
final double? aFlex = a.flex(cells);
|
||||
if (aFlex == null)
|
||||
return b.flex(cells);
|
||||
final double bFlex = b.flex(cells);
|
||||
final double? bFlex = b.flex(cells);
|
||||
if (bFlex == null)
|
||||
return null;
|
||||
return math.min(aFlex, bFlex);
|
||||
|
@ -362,43 +360,44 @@ class RenderTable extends RenderBox {
|
|||
/// null, then `children` must be null.
|
||||
/// * `children` must either be null or contain lists of all the same length.
|
||||
/// if `children` is not null, then `rows` must be null.
|
||||
/// * [columnWidths] may be null, in which case it defaults to an empty map.
|
||||
/// * [defaultColumnWidth] must not be null.
|
||||
/// * [configuration] must not be null (but has a default value).
|
||||
RenderTable({
|
||||
int columns,
|
||||
int rows,
|
||||
Map<int, TableColumnWidth> columnWidths,
|
||||
int? columns,
|
||||
int? rows,
|
||||
Map<int, TableColumnWidth>? columnWidths,
|
||||
TableColumnWidth defaultColumnWidth = const FlexColumnWidth(1.0),
|
||||
@required TextDirection textDirection,
|
||||
TableBorder border,
|
||||
List<Decoration> rowDecorations,
|
||||
required TextDirection textDirection,
|
||||
TableBorder? border,
|
||||
List<Decoration?>? rowDecorations,
|
||||
ImageConfiguration configuration = ImageConfiguration.empty,
|
||||
TableCellVerticalAlignment defaultVerticalAlignment = TableCellVerticalAlignment.top,
|
||||
TextBaseline textBaseline,
|
||||
List<List<RenderBox>> children,
|
||||
TextBaseline? textBaseline,
|
||||
List<List<RenderBox>>? children,
|
||||
}) : assert(columns == null || columns >= 0),
|
||||
assert(rows == null || rows >= 0),
|
||||
assert(rows == null || children == null),
|
||||
assert(defaultColumnWidth != null),
|
||||
assert(textDirection != null),
|
||||
assert(configuration != null),
|
||||
_textDirection = textDirection {
|
||||
_columns = columns ?? (children != null && children.isNotEmpty ? children.first.length : 0);
|
||||
_rows = rows ?? 0;
|
||||
_textDirection = textDirection,
|
||||
_columns = columns ?? (children != null && children.isNotEmpty ? children.first.length : 0),
|
||||
_rows = rows ?? 0,
|
||||
_columnWidths = columnWidths ?? HashMap<int, TableColumnWidth>(),
|
||||
_defaultColumnWidth = defaultColumnWidth,
|
||||
_border = border,
|
||||
_textBaseline = textBaseline,
|
||||
_defaultVerticalAlignment = defaultVerticalAlignment,
|
||||
_configuration = configuration {
|
||||
_children = <RenderBox>[]..length = _columns * _rows;
|
||||
_columnWidths = columnWidths ?? HashMap<int, TableColumnWidth>();
|
||||
_defaultColumnWidth = defaultColumnWidth;
|
||||
_border = border;
|
||||
this.rowDecorations = rowDecorations; // must use setter to initialize box painters array
|
||||
_configuration = configuration;
|
||||
_defaultVerticalAlignment = defaultVerticalAlignment;
|
||||
_textBaseline = textBaseline;
|
||||
children?.forEach(addRow);
|
||||
}
|
||||
|
||||
// Children are stored in row-major order.
|
||||
// _children.length must be rows * columns
|
||||
List<RenderBox> _children = const <RenderBox>[];
|
||||
List<RenderBox?> _children = const <RenderBox?>[];
|
||||
|
||||
/// The number of vertical alignment lines in this table.
|
||||
///
|
||||
|
@ -415,9 +414,9 @@ class RenderTable extends RenderBox {
|
|||
if (value == columns)
|
||||
return;
|
||||
final int oldColumns = columns;
|
||||
final List<RenderBox> oldChildren = _children;
|
||||
final List<RenderBox?> oldChildren = _children;
|
||||
_columns = value;
|
||||
_children = <RenderBox>[]..length = columns * rows;
|
||||
_children = List<RenderBox?>.filled(columns * rows, null, growable: false);
|
||||
final int columnsToCopy = math.min(columns, oldColumns);
|
||||
for (int y = 0; y < rows; y += 1) {
|
||||
for (int x = 0; x < columnsToCopy; x += 1)
|
||||
|
@ -428,7 +427,7 @@ class RenderTable extends RenderBox {
|
|||
for (int x = columns; x < oldColumns; x += 1) {
|
||||
final int xy = x + y * oldColumns;
|
||||
if (oldChildren[xy] != null)
|
||||
dropChild(oldChildren[xy]);
|
||||
dropChild(oldChildren[xy]!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -449,7 +448,7 @@ class RenderTable extends RenderBox {
|
|||
if (_rows > value) {
|
||||
for (int xy = columns * value; xy < _children.length; xy += 1) {
|
||||
if (_children[xy] != null)
|
||||
dropChild(_children[xy]);
|
||||
dropChild(_children[xy]!);
|
||||
}
|
||||
}
|
||||
_rows = value;
|
||||
|
@ -466,13 +465,18 @@ class RenderTable extends RenderBox {
|
|||
/// sizing algorithms are used here. In particular, [IntrinsicColumnWidth] is
|
||||
/// quite expensive because it needs to measure each cell in the column to
|
||||
/// determine the intrinsic size of the column.
|
||||
Map<int, TableColumnWidth> get columnWidths => Map<int, TableColumnWidth>.unmodifiable(_columnWidths);
|
||||
///
|
||||
/// This property can never return null. If it is set to null, and the existing
|
||||
/// map is not empty, then the value is replaced by an empty map. (If it is set
|
||||
/// to null while the current value is an empty map, the value is not changed.)
|
||||
Map<int, TableColumnWidth>? get columnWidths => Map<int, TableColumnWidth>.unmodifiable(_columnWidths);
|
||||
Map<int, TableColumnWidth> _columnWidths;
|
||||
set columnWidths(Map<int, TableColumnWidth> value) {
|
||||
value ??= HashMap<int, TableColumnWidth>();
|
||||
set columnWidths(Map<int, TableColumnWidth>? value) {
|
||||
if (_columnWidths == value)
|
||||
return;
|
||||
_columnWidths = value;
|
||||
if (_columnWidths.isEmpty && value == null)
|
||||
return;
|
||||
_columnWidths = value ?? HashMap<int, TableColumnWidth>();
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
|
@ -510,9 +514,9 @@ class RenderTable extends RenderBox {
|
|||
}
|
||||
|
||||
/// The style to use when painting the boundary and interior divisions of the table.
|
||||
TableBorder get border => _border;
|
||||
TableBorder _border;
|
||||
set border(TableBorder value) {
|
||||
TableBorder? get border => _border;
|
||||
TableBorder? _border;
|
||||
set border(TableBorder? value) {
|
||||
if (border == value)
|
||||
return;
|
||||
_border = value;
|
||||
|
@ -527,17 +531,17 @@ class RenderTable extends RenderBox {
|
|||
List<Decoration> get rowDecorations => List<Decoration>.unmodifiable(_rowDecorations ?? const <Decoration>[]);
|
||||
// _rowDecorations and _rowDecorationPainters need to be in sync. They have to
|
||||
// either both be null or have same length.
|
||||
List<Decoration> _rowDecorations;
|
||||
List<BoxPainter> _rowDecorationPainters;
|
||||
set rowDecorations(List<Decoration> value) {
|
||||
List<Decoration?>? _rowDecorations;
|
||||
List<BoxPainter?>? _rowDecorationPainters;
|
||||
set rowDecorations(List<Decoration?>? value) {
|
||||
if (_rowDecorations == value)
|
||||
return;
|
||||
_rowDecorations = value;
|
||||
if (_rowDecorationPainters != null) {
|
||||
for (final BoxPainter painter in _rowDecorationPainters)
|
||||
for (final BoxPainter? painter in _rowDecorationPainters!)
|
||||
painter?.dispose();
|
||||
}
|
||||
_rowDecorationPainters = _rowDecorations != null ? List<BoxPainter>(_rowDecorations.length) : null;
|
||||
_rowDecorationPainters = _rowDecorations != null ? List<BoxPainter?>.filled(_rowDecorations!.length, null, growable: false) : null;
|
||||
}
|
||||
|
||||
/// The settings to pass to the [rowDecorations] when painting, so that they
|
||||
|
@ -557,6 +561,7 @@ class RenderTable extends RenderBox {
|
|||
TableCellVerticalAlignment get defaultVerticalAlignment => _defaultVerticalAlignment;
|
||||
TableCellVerticalAlignment _defaultVerticalAlignment;
|
||||
set defaultVerticalAlignment(TableCellVerticalAlignment value) {
|
||||
assert(value != null);
|
||||
if (_defaultVerticalAlignment == value)
|
||||
return;
|
||||
_defaultVerticalAlignment = value;
|
||||
|
@ -564,9 +569,9 @@ class RenderTable extends RenderBox {
|
|||
}
|
||||
|
||||
/// The text baseline to use when aligning rows using [TableCellVerticalAlignment.baseline].
|
||||
TextBaseline get textBaseline => _textBaseline;
|
||||
TextBaseline _textBaseline;
|
||||
set textBaseline(TextBaseline value) {
|
||||
TextBaseline? get textBaseline => _textBaseline;
|
||||
TextBaseline? _textBaseline;
|
||||
set textBaseline(TextBaseline? value) {
|
||||
if (_textBaseline == value)
|
||||
return;
|
||||
_textBaseline = value;
|
||||
|
@ -587,7 +592,7 @@ class RenderTable extends RenderBox {
|
|||
/// If the new cells contain any existing children of the table, those
|
||||
/// children are simply moved to their new location in the table rather than
|
||||
/// removed from the table and re-added.
|
||||
void setFlatChildren(int columns, List<RenderBox> cells) {
|
||||
void setFlatChildren(int columns, List<RenderBox?> cells) {
|
||||
if (cells == _children && columns == _columns)
|
||||
return;
|
||||
assert(columns >= 0);
|
||||
|
@ -599,7 +604,7 @@ class RenderTable extends RenderBox {
|
|||
assert(_rows == 0);
|
||||
return;
|
||||
}
|
||||
for (final RenderBox oldChild in _children) {
|
||||
for (final RenderBox? oldChild in _children) {
|
||||
if (oldChild != null)
|
||||
dropChild(oldChild);
|
||||
}
|
||||
|
@ -619,7 +624,7 @@ class RenderTable extends RenderBox {
|
|||
final int xyOld = x + y * _columns;
|
||||
final int xyNew = x + y * columns;
|
||||
if (_children[xyOld] != null && (x >= columns || xyNew >= cells.length || _children[xyOld] != cells[xyNew]))
|
||||
lostChildren.add(_children[xyOld]);
|
||||
lostChildren.add(_children[xyOld]!);
|
||||
}
|
||||
}
|
||||
// adopt cells that are arriving, and cross cells that are just moving off our list of lostChildren
|
||||
|
@ -630,7 +635,7 @@ class RenderTable extends RenderBox {
|
|||
final int xyOld = x + y * _columns;
|
||||
if (cells[xyNew] != null && (x >= _columns || y >= _rows || _children[xyOld] != cells[xyNew])) {
|
||||
if (!lostChildren.remove(cells[xyNew]))
|
||||
adoptChild(cells[xyNew]);
|
||||
adoptChild(cells[xyNew]!);
|
||||
}
|
||||
}
|
||||
y += 1;
|
||||
|
@ -646,13 +651,13 @@ class RenderTable extends RenderBox {
|
|||
}
|
||||
|
||||
/// Replaces the children of this table with the given cells.
|
||||
void setChildren(List<List<RenderBox>> cells) {
|
||||
void setChildren(List<List<RenderBox>>? cells) {
|
||||
// TODO(ianh): Make this smarter, like setFlatChildren
|
||||
if (cells == null) {
|
||||
setFlatChildren(0, null);
|
||||
setFlatChildren(0, const <RenderBox?>[]);
|
||||
return;
|
||||
}
|
||||
for (final RenderBox oldChild in _children) {
|
||||
for (final RenderBox? oldChild in _children) {
|
||||
if (oldChild != null)
|
||||
dropChild(oldChild);
|
||||
}
|
||||
|
@ -666,12 +671,12 @@ class RenderTable extends RenderBox {
|
|||
/// Adds a row to the end of the table.
|
||||
///
|
||||
/// The newly added children must not already have parents.
|
||||
void addRow(List<RenderBox> cells) {
|
||||
void addRow(List<RenderBox?> cells) {
|
||||
assert(cells.length == columns);
|
||||
assert(_children.length == rows * columns);
|
||||
_rows += 1;
|
||||
_children.addAll(cells);
|
||||
for (final RenderBox cell in cells) {
|
||||
for (final RenderBox? cell in cells) {
|
||||
if (cell != null)
|
||||
adoptChild(cell);
|
||||
}
|
||||
|
@ -683,13 +688,13 @@ class RenderTable extends RenderBox {
|
|||
/// If the given child is already located at the given position, this function
|
||||
/// does not modify the table. Otherwise, the given child must not already
|
||||
/// have a parent.
|
||||
void setChild(int x, int y, RenderBox value) {
|
||||
void setChild(int x, int y, RenderBox? value) {
|
||||
assert(x != null);
|
||||
assert(y != null);
|
||||
assert(x >= 0 && x < columns && y >= 0 && y < rows);
|
||||
assert(_children.length == rows * columns);
|
||||
final int xy = x + y * columns;
|
||||
final RenderBox oldChild = _children[xy];
|
||||
final RenderBox? oldChild = _children[xy];
|
||||
if (oldChild == value)
|
||||
return;
|
||||
if (oldChild != null)
|
||||
|
@ -702,7 +707,7 @@ class RenderTable extends RenderBox {
|
|||
@override
|
||||
void attach(PipelineOwner owner) {
|
||||
super.attach(owner);
|
||||
for (final RenderBox child in _children)
|
||||
for (final RenderBox? child in _children)
|
||||
child?.attach(owner);
|
||||
}
|
||||
|
||||
|
@ -710,18 +715,18 @@ class RenderTable extends RenderBox {
|
|||
void detach() {
|
||||
super.detach();
|
||||
if (_rowDecorationPainters != null) {
|
||||
for (final BoxPainter painter in _rowDecorationPainters)
|
||||
for (final BoxPainter? painter in _rowDecorationPainters!)
|
||||
painter?.dispose();
|
||||
_rowDecorationPainters = List<BoxPainter>(_rowDecorations.length);
|
||||
_rowDecorationPainters = List<BoxPainter?>.filled(_rowDecorations!.length, null, growable: false);
|
||||
}
|
||||
for (final RenderBox child in _children)
|
||||
for (final RenderBox? child in _children)
|
||||
child?.detach();
|
||||
}
|
||||
|
||||
@override
|
||||
void visitChildren(RenderObjectVisitor visitor) {
|
||||
assert(_children.length == rows * columns);
|
||||
for (final RenderBox child in _children) {
|
||||
for (final RenderBox? child in _children) {
|
||||
if (child != null)
|
||||
visitor(child);
|
||||
}
|
||||
|
@ -762,7 +767,7 @@ class RenderTable extends RenderBox {
|
|||
double rowHeight = 0.0;
|
||||
for (int x = 0; x < columns; x += 1) {
|
||||
final int xy = x + y * columns;
|
||||
final RenderBox child = _children[xy];
|
||||
final RenderBox? child = _children[xy];
|
||||
if (child != null)
|
||||
rowHeight = math.max(rowHeight, child.getMaxIntrinsicHeight(widths[x]));
|
||||
}
|
||||
|
@ -776,9 +781,9 @@ class RenderTable extends RenderBox {
|
|||
return computeMinIntrinsicHeight(width);
|
||||
}
|
||||
|
||||
double _baselineDistance;
|
||||
double? _baselineDistance;
|
||||
@override
|
||||
double computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
double? computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
// returns the baseline of the first cell that has a baseline in the first row
|
||||
assert(!debugNeedsLayout);
|
||||
return _baselineDistance;
|
||||
|
@ -791,7 +796,7 @@ class RenderTable extends RenderBox {
|
|||
Iterable<RenderBox> column(int x) sync* {
|
||||
for (int y = 0; y < rows; y += 1) {
|
||||
final int xy = x + y * columns;
|
||||
final RenderBox child = _children[xy];
|
||||
final RenderBox? child = _children[xy];
|
||||
if (child != null)
|
||||
yield child;
|
||||
}
|
||||
|
@ -805,7 +810,7 @@ class RenderTable extends RenderBox {
|
|||
final int start = y * columns;
|
||||
final int end = (y + 1) * columns;
|
||||
for (int xy = start; xy < end; xy += 1) {
|
||||
final RenderBox child = _children[xy];
|
||||
final RenderBox? child = _children[xy];
|
||||
if (child != null)
|
||||
yield child;
|
||||
}
|
||||
|
@ -825,9 +830,9 @@ class RenderTable extends RenderBox {
|
|||
// necessary, applying minimum column widths as we go
|
||||
|
||||
// 1. apply ideal widths, and collect information we'll need later
|
||||
final List<double> widths = List<double>(columns);
|
||||
final List<double> minWidths = List<double>(columns);
|
||||
final List<double> flexes = List<double>(columns);
|
||||
final List<double> widths = List<double>.filled(columns, 0.0, growable: false);
|
||||
final List<double> minWidths = List<double>.filled(columns, 0.0, growable: false);
|
||||
final List<double?> flexes = List<double?>.filled(columns, null, growable: false);
|
||||
double tableWidth = 0.0; // running tally of the sum of widths[x] for all x
|
||||
double unflexedTableWidth = 0.0; // sum of the maxIntrinsicWidths of any column that has null flex
|
||||
double totalFlex = 0.0;
|
||||
|
@ -847,17 +852,16 @@ class RenderTable extends RenderBox {
|
|||
minWidths[x] = minIntrinsicWidth;
|
||||
assert(maxIntrinsicWidth >= minIntrinsicWidth);
|
||||
// collect flex information while we're at it
|
||||
final double flex = columnWidth.flex(columnCells);
|
||||
final double? flex = columnWidth.flex(columnCells);
|
||||
if (flex != null) {
|
||||
assert(flex.isFinite);
|
||||
assert(flex > 0.0);
|
||||
flexes[x] = flex;
|
||||
totalFlex += flex;
|
||||
} else {
|
||||
unflexedTableWidth += maxIntrinsicWidth;
|
||||
unflexedTableWidth = unflexedTableWidth + maxIntrinsicWidth;
|
||||
}
|
||||
}
|
||||
assert(!widths.any((double value) => value == null));
|
||||
final double maxWidthConstraint = constraints.maxWidth;
|
||||
final double minWidthConstraint = constraints.minWidth;
|
||||
|
||||
|
@ -878,7 +882,7 @@ class RenderTable extends RenderBox {
|
|||
assert(remainingWidth >= 0.0);
|
||||
for (int x = 0; x < columns; x += 1) {
|
||||
if (flexes[x] != null) {
|
||||
final double flexedWidth = remainingWidth * flexes[x] / totalFlex;
|
||||
final double flexedWidth = remainingWidth * flexes[x]! / totalFlex;
|
||||
assert(flexedWidth.isFinite);
|
||||
assert(flexedWidth >= 0.0);
|
||||
if (widths[x] < flexedWidth) {
|
||||
|
@ -897,15 +901,11 @@ class RenderTable extends RenderBox {
|
|||
else if (tableWidth < minWidthConstraint) {
|
||||
final double delta = (minWidthConstraint - tableWidth) / columns;
|
||||
for (int x = 0; x < columns; x += 1)
|
||||
widths[x] += delta;
|
||||
widths[x] = widths[x] + delta;
|
||||
tableWidth = minWidthConstraint;
|
||||
}
|
||||
|
||||
// beyond this point, unflexedTableWidth is no longer valid
|
||||
assert(() {
|
||||
unflexedTableWidth = null;
|
||||
return true;
|
||||
}());
|
||||
|
||||
// 4. apply the maximum width of the table, shrinking columns as
|
||||
// necessary, applying minimum column widths as we go
|
||||
|
@ -932,7 +932,7 @@ class RenderTable extends RenderBox {
|
|||
double newTotalFlex = 0.0;
|
||||
for (int x = 0; x < columns; x += 1) {
|
||||
if (flexes[x] != null) {
|
||||
final double newWidth = widths[x] - deficit * flexes[x] / totalFlex;
|
||||
final double newWidth = widths[x] - deficit * flexes[x]! / totalFlex;
|
||||
assert(newWidth.isFinite);
|
||||
if (newWidth <= minWidths[x]) {
|
||||
// shrank to minimum
|
||||
|
@ -943,7 +943,7 @@ class RenderTable extends RenderBox {
|
|||
} else {
|
||||
deficit -= widths[x] - newWidth;
|
||||
widths[x] = newWidth;
|
||||
newTotalFlex += flexes[x];
|
||||
newTotalFlex += flexes[x]!;
|
||||
}
|
||||
assert(widths[x] >= 0.0);
|
||||
}
|
||||
|
@ -968,7 +968,7 @@ class RenderTable extends RenderBox {
|
|||
widths[x] = minWidths[x];
|
||||
} else {
|
||||
deficit -= delta;
|
||||
widths[x] -= delta;
|
||||
widths[x] = widths[x] - delta;
|
||||
newAvailableColumns += 1;
|
||||
}
|
||||
}
|
||||
|
@ -981,7 +981,7 @@ class RenderTable extends RenderBox {
|
|||
|
||||
// cache the table geometry for painting purposes
|
||||
final List<double> _rowTops = <double>[];
|
||||
Iterable<double> _columnLefts;
|
||||
Iterable<double>? _columnLefts;
|
||||
|
||||
/// Returns the position and dimensions of the box that the given
|
||||
/// row covers, in this render object's coordinate space (so the
|
||||
|
@ -1010,7 +1010,7 @@ class RenderTable extends RenderBox {
|
|||
return;
|
||||
}
|
||||
final List<double> widths = _computeColumnWidths(constraints);
|
||||
final List<double> positions = List<double>(columns);
|
||||
final List<double> positions = List<double>.filled(columns, 0.0, growable: false);
|
||||
double tableWidth;
|
||||
switch (textDirection) {
|
||||
case TextDirection.rtl:
|
||||
|
@ -1028,7 +1028,6 @@ class RenderTable extends RenderBox {
|
|||
tableWidth = positions.last + widths.last;
|
||||
break;
|
||||
}
|
||||
assert(!positions.any((double value) => value == null));
|
||||
_rowTops.clear();
|
||||
_baselineDistance = null;
|
||||
// then, lay out each row
|
||||
|
@ -1039,10 +1038,10 @@ class RenderTable extends RenderBox {
|
|||
bool haveBaseline = false;
|
||||
double beforeBaselineDistance = 0.0;
|
||||
double afterBaselineDistance = 0.0;
|
||||
final List<double> baselines = List<double>(columns);
|
||||
final List<double> baselines = List<double>.filled(columns, 0.0, growable: false);
|
||||
for (int x = 0; x < columns; x += 1) {
|
||||
final int xy = x + y * columns;
|
||||
final RenderBox child = _children[xy];
|
||||
final RenderBox? child = _children[xy];
|
||||
if (child != null) {
|
||||
final TableCellParentData childParentData = child.parentData as TableCellParentData;
|
||||
assert(childParentData != null);
|
||||
|
@ -1052,7 +1051,7 @@ class RenderTable extends RenderBox {
|
|||
case TableCellVerticalAlignment.baseline:
|
||||
assert(textBaseline != null);
|
||||
child.layout(BoxConstraints.tightFor(width: widths[x]), parentUsesSize: true);
|
||||
final double childBaseline = child.getDistanceToBaseline(textBaseline, onlyReal: true);
|
||||
final double? childBaseline = child.getDistanceToBaseline(textBaseline!, onlyReal: true);
|
||||
if (childBaseline != null) {
|
||||
beforeBaselineDistance = math.max(beforeBaselineDistance, childBaseline);
|
||||
afterBaselineDistance = math.max(afterBaselineDistance, child.size.height - childBaseline);
|
||||
|
@ -1081,7 +1080,7 @@ class RenderTable extends RenderBox {
|
|||
}
|
||||
for (int x = 0; x < columns; x += 1) {
|
||||
final int xy = x + y * columns;
|
||||
final RenderBox child = _children[xy];
|
||||
final RenderBox? child = _children[xy];
|
||||
if (child != null) {
|
||||
final TableCellParentData childParentData = child.parentData as TableCellParentData;
|
||||
switch (childParentData.verticalAlignment ?? defaultVerticalAlignment) {
|
||||
|
@ -1113,18 +1112,18 @@ class RenderTable extends RenderBox {
|
|||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
|
||||
assert(_children.length == rows * columns);
|
||||
for (int index = _children.length - 1; index >= 0; index -= 1) {
|
||||
final RenderBox child = _children[index];
|
||||
final RenderBox? child = _children[index];
|
||||
if (child != null) {
|
||||
final BoxParentData childParentData = child.parentData as BoxParentData;
|
||||
final bool isHit = result.addWithPaintOffset(
|
||||
offset: childParentData.offset,
|
||||
position: position,
|
||||
hitTest: (BoxHitTestResult result, Offset transformed) {
|
||||
hitTest: (BoxHitTestResult result, Offset? transformed) {
|
||||
assert(transformed == position - childParentData.offset);
|
||||
return child.hitTest(result, position: transformed);
|
||||
return child.hitTest(result, position: transformed!);
|
||||
},
|
||||
);
|
||||
if (isHit)
|
||||
|
@ -1140,20 +1139,20 @@ class RenderTable extends RenderBox {
|
|||
if (rows * columns == 0) {
|
||||
if (border != null) {
|
||||
final Rect borderRect = Rect.fromLTWH(offset.dx, offset.dy, size.width, 0.0);
|
||||
border.paint(context.canvas, borderRect, rows: const <double>[], columns: const <double>[]);
|
||||
border!.paint(context.canvas, borderRect, rows: const <double>[], columns: const <double>[]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
assert(_rowTops.length == rows + 1);
|
||||
if (_rowDecorations != null) {
|
||||
assert(_rowDecorations.length == _rowDecorationPainters.length);
|
||||
assert(_rowDecorations!.length == _rowDecorationPainters!.length);
|
||||
final Canvas canvas = context.canvas;
|
||||
for (int y = 0; y < rows; y += 1) {
|
||||
if (_rowDecorations.length <= y)
|
||||
if (_rowDecorations!.length <= y)
|
||||
break;
|
||||
if (_rowDecorations[y] != null) {
|
||||
_rowDecorationPainters[y] ??= _rowDecorations[y].createBoxPainter(markNeedsPaint);
|
||||
_rowDecorationPainters[y].paint(
|
||||
if (_rowDecorations![y] != null) {
|
||||
_rowDecorationPainters![y] ??= _rowDecorations![y]!.createBoxPainter(markNeedsPaint);
|
||||
_rowDecorationPainters![y]!.paint(
|
||||
canvas,
|
||||
Offset(offset.dx, offset.dy + _rowTops[y]),
|
||||
configuration.copyWith(size: Size(size.width, _rowTops[y+1] - _rowTops[y])),
|
||||
|
@ -1162,22 +1161,22 @@ class RenderTable extends RenderBox {
|
|||
}
|
||||
}
|
||||
for (int index = 0; index < _children.length; index += 1) {
|
||||
final RenderBox child = _children[index];
|
||||
final RenderBox? child = _children[index];
|
||||
if (child != null) {
|
||||
final BoxParentData childParentData = child.parentData as BoxParentData;
|
||||
context.paintChild(child, childParentData.offset + offset);
|
||||
}
|
||||
}
|
||||
assert(_rows == _rowTops.length - 1);
|
||||
assert(_columns == _columnLefts.length);
|
||||
assert(_columns == _columnLefts!.length);
|
||||
if (border != null) {
|
||||
// The border rect might not fill the entire height of this render object
|
||||
// if the rows underflow. We always force the columns to fill the width of
|
||||
// the render object, which means the columns cannot underflow.
|
||||
final Rect borderRect = Rect.fromLTWH(offset.dx, offset.dy, size.width, _rowTops.last);
|
||||
final Iterable<double> rows = _rowTops.getRange(1, _rowTops.length - 1);
|
||||
final Iterable<double> columns = _columnLefts.skip(1);
|
||||
border.paint(context.canvas, borderRect, rows: rows, columns: columns);
|
||||
final Iterable<double> columns = _columnLefts!.skip(1);
|
||||
border!.paint(context.canvas, borderRect, rows: rows, columns: columns);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1189,7 +1188,7 @@ class RenderTable extends RenderBox {
|
|||
properties.add(DiagnosticsProperty<TableColumnWidth>('default column width', defaultColumnWidth));
|
||||
properties.add(MessageProperty('table size', '$columns\u00D7$rows'));
|
||||
properties.add(IterableProperty<String>('column offsets', _columnLefts?.map(debugFormatDouble), ifNull: 'unknown'));
|
||||
properties.add(IterableProperty<String>('row offsets', _rowTops?.map(debugFormatDouble), ifNull: 'unknown'));
|
||||
properties.add(IterableProperty<String>('row offsets', _rowTops.map(debugFormatDouble), ifNull: 'unknown'));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -1202,7 +1201,7 @@ class RenderTable extends RenderBox {
|
|||
for (int y = 0; y < rows; y += 1) {
|
||||
for (int x = 0; x < columns; x += 1) {
|
||||
final int xy = x + y * columns;
|
||||
final RenderBox child = _children[xy];
|
||||
final RenderBox? child = _children[xy];
|
||||
final String name = 'child ($x, $y)';
|
||||
if (child != null)
|
||||
children.add(child.toDiagnosticsNode(name: name));
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/painting.dart' hide Border;
|
||||
|
||||
|
@ -150,12 +148,12 @@ class TableBorder {
|
|||
/// borders.
|
||||
///
|
||||
/// {@macro dart.ui.shadow.lerp}
|
||||
static TableBorder lerp(TableBorder a, TableBorder b, double t) {
|
||||
static TableBorder? lerp(TableBorder? a, TableBorder? b, double t) {
|
||||
assert(t != null);
|
||||
if (a == null && b == null)
|
||||
return null;
|
||||
if (a == null)
|
||||
return b.scale(t);
|
||||
return b!.scale(t);
|
||||
if (b == null)
|
||||
return a.scale(1.0 - t);
|
||||
return TableBorder(
|
||||
|
@ -197,8 +195,8 @@ class TableBorder {
|
|||
void paint(
|
||||
Canvas canvas,
|
||||
Rect rect, {
|
||||
@required Iterable<double> rows,
|
||||
@required Iterable<double> columns,
|
||||
required Iterable<double> rows,
|
||||
required Iterable<double> columns,
|
||||
}) {
|
||||
// properties can't be null
|
||||
assert(top != null);
|
||||
|
|
|
@ -2,9 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'box.dart';
|
||||
import 'layer.dart';
|
||||
import 'object.dart';
|
||||
|
@ -40,7 +37,7 @@ class TextureBox extends RenderBox {
|
|||
/// Creates a box backed by the texture identified by [textureId], and use
|
||||
/// [filterQuality] to set texture's [FilterQuality].
|
||||
TextureBox({
|
||||
@required int textureId,
|
||||
required int textureId,
|
||||
FilterQuality filterQuality = FilterQuality.low,
|
||||
}) : assert(textureId != null),
|
||||
_textureId = textureId,
|
||||
|
@ -87,8 +84,6 @@ class TextureBox extends RenderBox {
|
|||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
if (_textureId == null)
|
||||
return;
|
||||
context.addLayer(TextureLayer(
|
||||
rect: Rect.fromLTWH(offset.dx, offset.dy, size.width, size.height),
|
||||
textureId: _textureId,
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/animation.dart';
|
||||
import 'package:flutter/painting.dart';
|
||||
|
||||
|
@ -17,17 +15,17 @@ import 'package:flutter/painting.dart';
|
|||
/// See also:
|
||||
///
|
||||
/// * [AlignmentTween], which interpolates between to [Alignment] objects.
|
||||
class FractionalOffsetTween extends Tween<FractionalOffset> {
|
||||
class FractionalOffsetTween extends Tween<FractionalOffset?> {
|
||||
/// Creates a fractional offset tween.
|
||||
///
|
||||
/// The [begin] and [end] properties may be null; the null value
|
||||
/// is treated as meaning the center.
|
||||
FractionalOffsetTween({ FractionalOffset begin, FractionalOffset end })
|
||||
FractionalOffsetTween({ FractionalOffset? begin, FractionalOffset? end })
|
||||
: super(begin: begin, end: end);
|
||||
|
||||
/// Returns the value this variable has at the given animation clock value.
|
||||
@override
|
||||
FractionalOffset lerp(double t) => FractionalOffset.lerp(begin, end, t);
|
||||
FractionalOffset? lerp(double t) => FractionalOffset.lerp(begin, end, t);
|
||||
}
|
||||
|
||||
/// An interpolation between two alignments.
|
||||
|
@ -41,17 +39,17 @@ class FractionalOffsetTween extends Tween<FractionalOffset> {
|
|||
///
|
||||
/// * [AlignmentGeometryTween], which interpolates between two
|
||||
/// [AlignmentGeometry] objects.
|
||||
class AlignmentTween extends Tween<Alignment> {
|
||||
class AlignmentTween extends Tween<Alignment?> {
|
||||
/// Creates a fractional offset tween.
|
||||
///
|
||||
/// The [begin] and [end] properties may be null; the null value
|
||||
/// is treated as meaning the center.
|
||||
AlignmentTween({ Alignment begin, Alignment end })
|
||||
AlignmentTween({ Alignment? begin, Alignment? end })
|
||||
: super(begin: begin, end: end);
|
||||
|
||||
/// Returns the value this variable has at the given animation clock value.
|
||||
@override
|
||||
Alignment lerp(double t) => Alignment.lerp(begin, end, t);
|
||||
Alignment? lerp(double t) => Alignment.lerp(begin, end, t);
|
||||
}
|
||||
|
||||
/// An interpolation between two [AlignmentGeometry].
|
||||
|
@ -64,17 +62,17 @@ class AlignmentTween extends Tween<Alignment> {
|
|||
/// See also:
|
||||
///
|
||||
/// * [AlignmentTween], which interpolates between two [Alignment] objects.
|
||||
class AlignmentGeometryTween extends Tween<AlignmentGeometry> {
|
||||
class AlignmentGeometryTween extends Tween<AlignmentGeometry?> {
|
||||
/// Creates a fractional offset geometry tween.
|
||||
///
|
||||
/// The [begin] and [end] properties may be null; the null value
|
||||
/// is treated as meaning the center.
|
||||
AlignmentGeometryTween({
|
||||
AlignmentGeometry begin,
|
||||
AlignmentGeometry end,
|
||||
AlignmentGeometry? begin,
|
||||
AlignmentGeometry? end,
|
||||
}) : super(begin: begin, end: end);
|
||||
|
||||
/// Returns the value this variable has at the given animation clock value.
|
||||
@override
|
||||
AlignmentGeometry lerp(double t) => AlignmentGeometry.lerp(begin, end, t);
|
||||
AlignmentGeometry? lerp(double t) => AlignmentGeometry.lerp(begin, end, t);
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:developer';
|
||||
import 'dart:io' show Platform;
|
||||
import 'dart:ui' as ui show Scene, SceneBuilder, Window;
|
||||
|
@ -57,9 +55,9 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
|
|||
///
|
||||
/// The [configuration] must not be null.
|
||||
RenderView({
|
||||
RenderBox child,
|
||||
@required ViewConfiguration configuration,
|
||||
@required ui.Window window,
|
||||
RenderBox? child,
|
||||
required ViewConfiguration configuration,
|
||||
required ui.Window window,
|
||||
}) : assert(configuration != null),
|
||||
_configuration = configuration,
|
||||
_window = window {
|
||||
|
@ -120,7 +118,7 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
|
|||
)
|
||||
void scheduleInitialFrame() {
|
||||
prepareInitialFrame();
|
||||
owner.requestVisualUpdate();
|
||||
owner!.requestVisualUpdate();
|
||||
}
|
||||
|
||||
/// Bootstrap the rendering pipeline by preparing the first frame.
|
||||
|
@ -139,7 +137,7 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
|
|||
assert(_rootTransform != null);
|
||||
}
|
||||
|
||||
Matrix4 _rootTransform;
|
||||
Matrix4? _rootTransform;
|
||||
|
||||
TransformLayer _updateMatricesAndCreateNewRootLayer() {
|
||||
_rootTransform = configuration.toMatrix();
|
||||
|
@ -166,11 +164,11 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
|
|||
assert(_size.isFinite);
|
||||
|
||||
if (child != null)
|
||||
child.layout(BoxConstraints.tight(_size));
|
||||
child!.layout(BoxConstraints.tight(_size));
|
||||
}
|
||||
|
||||
@override
|
||||
void rotate({ int oldAngle, int newAngle, Duration time }) {
|
||||
void rotate({ int? oldAngle, int? newAngle, Duration? time }) {
|
||||
assert(false); // nobody tells the screen to rotate, the whole rotate() dance is started from our performResize()
|
||||
}
|
||||
|
||||
|
@ -184,9 +182,9 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
|
|||
/// which is to say, in logical pixels. This is not necessarily the same
|
||||
/// coordinate system as that expected by the root [Layer], which will
|
||||
/// normally be in physical (device) pixels.
|
||||
bool hitTest(HitTestResult result, { Offset position }) {
|
||||
bool hitTest(HitTestResult result, { required Offset position }) {
|
||||
if (child != null)
|
||||
child.hitTest(BoxHitTestResult.wrap(result), position: position);
|
||||
child!.hitTest(BoxHitTestResult.wrap(result), position: position);
|
||||
result.add(HitTestEntry(this));
|
||||
return true;
|
||||
}
|
||||
|
@ -198,6 +196,7 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
|
|||
/// * [Layer.findAllAnnotations], which is used by this method to find all
|
||||
/// [AnnotatedRegionLayer]s annotated for mouse tracking.
|
||||
HitTestResult hitTestMouseTrackers(Offset position) {
|
||||
assert(position != null);
|
||||
// Layer hit testing is done using device pixels, so we have to convert
|
||||
// the logical coordinates of the event location back to device pixels
|
||||
// here.
|
||||
|
@ -212,13 +211,13 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
|
|||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
if (child != null)
|
||||
context.paintChild(child, offset);
|
||||
context.paintChild(child!, offset);
|
||||
}
|
||||
|
||||
@override
|
||||
void applyPaintTransform(RenderBox child, Matrix4 transform) {
|
||||
assert(_rootTransform != null);
|
||||
transform.multiply(_rootTransform);
|
||||
transform.multiply(_rootTransform!);
|
||||
super.applyPaintTransform(child, transform);
|
||||
}
|
||||
|
||||
|
@ -229,7 +228,7 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
|
|||
Timeline.startSync('Compositing', arguments: timelineArgumentsIndicatingLandmarkEvent);
|
||||
try {
|
||||
final ui.SceneBuilder builder = ui.SceneBuilder();
|
||||
final ui.Scene scene = layer.buildScene(builder);
|
||||
final ui.Scene scene = layer!.buildScene(builder);
|
||||
if (automaticSystemUiAdjustment)
|
||||
_updateSystemChrome();
|
||||
_window.render(scene);
|
||||
|
@ -248,12 +247,12 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
|
|||
final Rect bounds = paintBounds;
|
||||
final Offset top = Offset(bounds.center.dx, _window.padding.top / _window.devicePixelRatio);
|
||||
final Offset bottom = Offset(bounds.center.dx, bounds.center.dy - _window.padding.bottom / _window.devicePixelRatio);
|
||||
final SystemUiOverlayStyle upperOverlayStyle = layer.find<SystemUiOverlayStyle>(top);
|
||||
final SystemUiOverlayStyle? upperOverlayStyle = layer!.find<SystemUiOverlayStyle>(top);
|
||||
// Only android has a customizable system navigation bar.
|
||||
SystemUiOverlayStyle lowerOverlayStyle;
|
||||
SystemUiOverlayStyle? lowerOverlayStyle;
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
lowerOverlayStyle = layer.find<SystemUiOverlayStyle>(bottom);
|
||||
lowerOverlayStyle = layer!.find<SystemUiOverlayStyle>(bottom);
|
||||
break;
|
||||
case TargetPlatform.fuchsia:
|
||||
case TargetPlatform.iOS:
|
||||
|
@ -282,7 +281,7 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
|
|||
@override
|
||||
Rect get semanticBounds {
|
||||
assert(_rootTransform != null);
|
||||
return MatrixUtils.transformRect(_rootTransform, Offset.zero & size);
|
||||
return MatrixUtils.transformRect(_rootTransform!, Offset.zero & size);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/animation.dart';
|
||||
|
@ -35,18 +33,18 @@ abstract class RenderAbstractViewport extends RenderObject {
|
|||
// This class is intended to be used as an interface, and should not be
|
||||
// extended directly; this constructor prevents instantiation and extension.
|
||||
// ignore: unused_element
|
||||
factory RenderAbstractViewport._() => null;
|
||||
factory RenderAbstractViewport._() => throw Error();
|
||||
|
||||
/// Returns the [RenderAbstractViewport] that most tightly encloses the given
|
||||
/// render object.
|
||||
///
|
||||
/// If the object does not have a [RenderAbstractViewport] as an ancestor,
|
||||
/// this function returns null.
|
||||
static RenderAbstractViewport of(RenderObject object) {
|
||||
static RenderAbstractViewport? of(RenderObject? object) {
|
||||
while (object != null) {
|
||||
if (object is RenderAbstractViewport)
|
||||
return object;
|
||||
object = object.parent as RenderObject;
|
||||
object = object.parent as RenderObject?;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -78,15 +76,15 @@ abstract class RenderAbstractViewport extends RenderObject {
|
|||
/// See also:
|
||||
///
|
||||
/// * [RevealedOffset], which describes the return value of this method.
|
||||
RevealedOffset getOffsetToReveal(RenderObject target, double alignment, { Rect rect });
|
||||
RevealedOffset getOffsetToReveal(RenderObject target, double alignment, { Rect? rect });
|
||||
|
||||
/// The default value for the cache extent of the viewport.
|
||||
///
|
||||
/// This default assumes [CacheExtentStyle.pixel].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [RenderViewportBase.cacheExtent] for a definition of the cache extent.
|
||||
@protected
|
||||
@visibleForTesting
|
||||
static const double defaultCacheExtent = 250.0;
|
||||
}
|
||||
|
||||
|
@ -99,8 +97,8 @@ class RevealedOffset {
|
|||
|
||||
/// Instantiates a return value for [RenderAbstractViewport.getOffsetToReveal].
|
||||
const RevealedOffset({
|
||||
@required this.offset,
|
||||
@required this.rect,
|
||||
required this.offset,
|
||||
required this.rect,
|
||||
}) : assert(offset != null),
|
||||
assert(rect != null);
|
||||
|
||||
|
@ -167,11 +165,15 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
extends RenderBox with ContainerRenderObjectMixin<RenderSliver, ParentDataClass>
|
||||
implements RenderAbstractViewport {
|
||||
/// Initializes fields for subclasses.
|
||||
///
|
||||
/// The [cacheExtent], if null, defaults to [RenderAbstractViewport.defaultCacheExtent].
|
||||
///
|
||||
/// The [cacheExtent] must be specified if [cacheExtentStyle] is not [CacheExtentStyle.pixel].
|
||||
RenderViewportBase({
|
||||
AxisDirection axisDirection = AxisDirection.down,
|
||||
@required AxisDirection crossAxisDirection,
|
||||
@required ViewportOffset offset,
|
||||
double cacheExtent,
|
||||
required AxisDirection crossAxisDirection,
|
||||
required ViewportOffset offset,
|
||||
double? cacheExtent,
|
||||
CacheExtentStyle cacheExtentStyle = CacheExtentStyle.pixel,
|
||||
Clip clipBehavior = Clip.hardEdge,
|
||||
}) : assert(axisDirection != null),
|
||||
|
@ -213,7 +215,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
@override
|
||||
void visitChildrenForSemantics(RenderObjectVisitor visitor) {
|
||||
childrenInPaintOrder
|
||||
.where((RenderSliver sliver) => sliver.geometry.visible || sliver.geometry.cacheExtent > 0.0)
|
||||
.where((RenderSliver sliver) => sliver.geometry!.visible || sliver.geometry!.cacheExtent > 0.0)
|
||||
.forEach(visitor);
|
||||
}
|
||||
|
||||
|
@ -277,6 +279,11 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
markNeedsLayout();
|
||||
}
|
||||
|
||||
// TODO(ianh): cacheExtent/cacheExtentStyle should be a single
|
||||
// object that specifies both the scalar value and the unit, not a
|
||||
// pair of independent setters. Changing that would allow a more
|
||||
// rational API and would let us make the getter non-nullable.
|
||||
|
||||
/// {@template flutter.rendering.viewport.cacheExtent}
|
||||
/// The viewport has an area before and after the visible area to cache items
|
||||
/// that are about to become visible when the user scrolls.
|
||||
|
@ -295,10 +302,19 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
/// viewport to an invisible item in the cache area, the framework will bring
|
||||
/// that item into view with an (implicit) scroll action.
|
||||
/// {@endtemplate}
|
||||
double get cacheExtent => _cacheExtent;
|
||||
///
|
||||
/// The getter can never return null, but the field is nullable
|
||||
/// because the setter can be set to null to reset the value to
|
||||
/// [RenderAbstractViewport.defaultCacheExtent] (in which case
|
||||
/// [cacheExtentStyle] must be [CacheExtentStyle.pixel]).
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [cacheExtentStyle], which controls the units of the [cacheExtent].
|
||||
double? get cacheExtent => _cacheExtent;
|
||||
double _cacheExtent;
|
||||
set cacheExtent(double value) {
|
||||
value = value ?? RenderAbstractViewport.defaultCacheExtent;
|
||||
set cacheExtent(double? value) {
|
||||
value ??= RenderAbstractViewport.defaultCacheExtent;
|
||||
assert(value != null);
|
||||
if (value == _cacheExtent)
|
||||
return;
|
||||
|
@ -311,18 +327,23 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
/// When the style is [CacheExtentStyle.viewport], it is the main axis extent
|
||||
/// of the viewport multiplied by the requested cache extent, which is still
|
||||
/// expressed in pixels.
|
||||
double _calculatedCacheExtent;
|
||||
double? _calculatedCacheExtent;
|
||||
|
||||
/// {@template flutter.rendering.viewport.cacheExtentStyle}
|
||||
/// Controls how the [cacheExtent] is interpreted.
|
||||
///
|
||||
/// If set to [CacheExtentStyle.pixel], the [cacheExtent] will be treated as
|
||||
/// a logical pixels.
|
||||
/// If set to [CacheExtentStyle.pixel], the [cacheExtent] will be
|
||||
/// treated as a logical pixels, and the default [cacheExtent] is
|
||||
/// [RenderAbstractViewport.defaultCacheExtent].
|
||||
///
|
||||
/// If set to [CacheExtentStyle.viewport], the [cacheExtent] will be treated
|
||||
/// as a multiplier for the main axis extent of the viewport. In this case,
|
||||
/// the [cacheExtent] must not be null.
|
||||
/// If set to [CacheExtentStyle.viewport], the [cacheExtent] will be
|
||||
/// treated as a multiplier for the main axis extent of the
|
||||
/// viewport. In this case there is no default [cacheExtent]; it
|
||||
/// must be explicitly specified.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// Changing the [cacheExtentStyle] without also changing the [cacheExtent]
|
||||
/// is rarely the correct choice.
|
||||
CacheExtentStyle get cacheExtentStyle => _cacheExtentStyle;
|
||||
CacheExtentStyle _cacheExtentStyle;
|
||||
set cacheExtentStyle(CacheExtentStyle value) {
|
||||
|
@ -449,17 +470,17 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
/// function repeatedly until it returns 0.0.
|
||||
@protected
|
||||
double layoutChildSequence({
|
||||
@required RenderSliver child,
|
||||
@required double scrollOffset,
|
||||
@required double overlap,
|
||||
@required double layoutOffset,
|
||||
@required double remainingPaintExtent,
|
||||
@required double mainAxisExtent,
|
||||
@required double crossAxisExtent,
|
||||
@required GrowthDirection growthDirection,
|
||||
@required RenderSliver advance(RenderSliver child),
|
||||
@required double remainingCacheExtent,
|
||||
@required double cacheOrigin,
|
||||
required RenderSliver? child,
|
||||
required double scrollOffset,
|
||||
required double overlap,
|
||||
required double layoutOffset,
|
||||
required double remainingPaintExtent,
|
||||
required double mainAxisExtent,
|
||||
required double crossAxisExtent,
|
||||
required GrowthDirection growthDirection,
|
||||
required RenderSliver? Function(RenderSliver child) advance,
|
||||
required double remainingCacheExtent,
|
||||
required double cacheOrigin,
|
||||
}) {
|
||||
assert(scrollOffset.isFinite);
|
||||
assert(scrollOffset >= 0.0);
|
||||
|
@ -498,12 +519,12 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
cacheOrigin: correctedCacheOrigin,
|
||||
), parentUsesSize: true);
|
||||
|
||||
final SliverGeometry childLayoutGeometry = child.geometry;
|
||||
final SliverGeometry childLayoutGeometry = child.geometry!;
|
||||
assert(childLayoutGeometry.debugAssertIsValid());
|
||||
|
||||
// If there is a correction to apply, we'll have to start over.
|
||||
if (childLayoutGeometry.scrollOffsetCorrection != null)
|
||||
return childLayoutGeometry.scrollOffsetCorrection;
|
||||
return childLayoutGeometry.scrollOffsetCorrection!;
|
||||
|
||||
// We use the child's paint origin in our coordinate system as the
|
||||
// layoutOffset we store in the child's parent data.
|
||||
|
@ -578,7 +599,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
}
|
||||
|
||||
@override
|
||||
Rect describeSemanticsClip(RenderSliver child) {
|
||||
Rect describeSemanticsClip(RenderSliver? child) {
|
||||
assert(axis != null);
|
||||
|
||||
if (_calculatedCacheExtent == null) {
|
||||
|
@ -589,19 +610,18 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
case Axis.vertical:
|
||||
return Rect.fromLTRB(
|
||||
semanticBounds.left,
|
||||
semanticBounds.top - _calculatedCacheExtent,
|
||||
semanticBounds.top - _calculatedCacheExtent!,
|
||||
semanticBounds.right,
|
||||
semanticBounds.bottom + _calculatedCacheExtent,
|
||||
semanticBounds.bottom + _calculatedCacheExtent!,
|
||||
);
|
||||
case Axis.horizontal:
|
||||
return Rect.fromLTRB(
|
||||
semanticBounds.left - _calculatedCacheExtent,
|
||||
semanticBounds.left - _calculatedCacheExtent!,
|
||||
semanticBounds.top,
|
||||
semanticBounds.right + _calculatedCacheExtent,
|
||||
semanticBounds.right + _calculatedCacheExtent!,
|
||||
semanticBounds.bottom,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -617,7 +637,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
|
||||
void _paintContents(PaintingContext context, Offset offset) {
|
||||
for (final RenderSliver child in childrenInPaintOrder) {
|
||||
if (child.geometry.visible)
|
||||
if (child.geometry!.visible)
|
||||
context.paintChild(child, offset + paintOffsetOf(child));
|
||||
}
|
||||
}
|
||||
|
@ -631,15 +651,15 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
..strokeWidth = 1.0
|
||||
..color = const Color(0xFF00FF00);
|
||||
final Canvas canvas = context.canvas;
|
||||
RenderSliver child = firstChild;
|
||||
RenderSliver? child = firstChild;
|
||||
while (child != null) {
|
||||
Size size;
|
||||
switch (axis) {
|
||||
case Axis.vertical:
|
||||
size = Size(child.constraints.crossAxisExtent, child.geometry.layoutExtent);
|
||||
size = Size(child.constraints.crossAxisExtent, child.geometry!.layoutExtent);
|
||||
break;
|
||||
case Axis.horizontal:
|
||||
size = Size(child.geometry.layoutExtent, child.constraints.crossAxisExtent);
|
||||
size = Size(child.geometry!.layoutExtent, child.constraints.crossAxisExtent);
|
||||
break;
|
||||
}
|
||||
assert(size != null);
|
||||
|
@ -651,7 +671,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
|
||||
double mainAxisPosition, crossAxisPosition;
|
||||
switch (axis) {
|
||||
case Axis.vertical:
|
||||
|
@ -667,15 +687,14 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
assert(crossAxisPosition != null);
|
||||
final SliverHitTestResult sliverResult = SliverHitTestResult.wrap(result);
|
||||
for (final RenderSliver child in childrenInHitTestOrder) {
|
||||
if (!child.geometry.visible) {
|
||||
if (!child.geometry!.visible) {
|
||||
continue;
|
||||
}
|
||||
final Matrix4 transform = Matrix4.identity();
|
||||
applyPaintTransform(child, transform);
|
||||
final bool isHit = result.addWithPaintTransform(
|
||||
transform: transform,
|
||||
position: null, // Manually adapting from box to sliver position below.
|
||||
hitTest: (BoxHitTestResult result, Offset _) {
|
||||
applyPaintTransform(child, transform); // must be invertible
|
||||
final bool isHit = result.addWithOutOfBandPosition(
|
||||
paintTransform: transform,
|
||||
hitTest: (BoxHitTestResult result) {
|
||||
return child.hitTest(
|
||||
sliverResult,
|
||||
mainAxisPosition: computeChildMainAxisPosition(child, mainAxisPosition),
|
||||
|
@ -691,7 +710,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
}
|
||||
|
||||
@override
|
||||
RevealedOffset getOffsetToReveal(RenderObject target, double alignment, { Rect rect }) {
|
||||
RevealedOffset getOffsetToReveal(RenderObject target, double alignment, { Rect? rect }) {
|
||||
// Steps to convert `rect` (from a RenderBox coordinate system) to its
|
||||
// scroll offset within this viewport (not in the exact order):
|
||||
//
|
||||
|
@ -714,7 +733,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
// - `child` will be the last object before we reach this viewport, and
|
||||
// - `pivot` will be the last RenderBox before we reach this viewport.
|
||||
RenderObject child = target;
|
||||
RenderBox pivot;
|
||||
RenderBox? pivot;
|
||||
bool onlySlivers = target is RenderSliver; // ... between viewport and `target` (`target` included).
|
||||
while (child.parent != this) {
|
||||
final RenderObject parent = child.parent as RenderObject;
|
||||
|
@ -723,7 +742,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
pivot = child;
|
||||
}
|
||||
if (parent is RenderSliver) {
|
||||
leadingScrollOffset += parent.childScrollOffset(child);
|
||||
leadingScrollOffset += parent.childScrollOffset(child)!;
|
||||
} else {
|
||||
onlySlivers = false;
|
||||
leadingScrollOffset = 0.0;
|
||||
|
@ -763,13 +782,13 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
growthDirection = targetSliver.constraints.growthDirection;
|
||||
// TODO(LongCatIsLooong): make sure this works if `targetSliver` is a
|
||||
// persistent header, when #56413 relands.
|
||||
pivotExtent = targetSliver.geometry.scrollExtent;
|
||||
pivotExtent = targetSliver.geometry!.scrollExtent;
|
||||
if (rect == null) {
|
||||
switch (axis) {
|
||||
case Axis.horizontal:
|
||||
rect = Rect.fromLTWH(
|
||||
0, 0,
|
||||
targetSliver.geometry.scrollExtent,
|
||||
targetSliver.geometry!.scrollExtent,
|
||||
targetSliver.constraints.crossAxisExtent,
|
||||
);
|
||||
break;
|
||||
|
@ -777,14 +796,15 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
rect = Rect.fromLTWH(
|
||||
0, 0,
|
||||
targetSliver.constraints.crossAxisExtent,
|
||||
targetSliver.geometry.scrollExtent,
|
||||
targetSliver.geometry!.scrollExtent,
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
rectLocal = rect;
|
||||
} else {
|
||||
return RevealedOffset(offset: offset.pixels, rect: rect);
|
||||
assert(rect != null);
|
||||
return RevealedOffset(offset: offset.pixels, rect: rect!);
|
||||
}
|
||||
|
||||
assert(pivotExtent != null);
|
||||
|
@ -894,15 +914,14 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
assert(child.geometry != null);
|
||||
switch (applyGrowthDirectionToAxisDirection(axisDirection, growthDirection)) {
|
||||
case AxisDirection.up:
|
||||
return Offset(0.0, size.height - (layoutOffset + child.geometry.paintExtent));
|
||||
return Offset(0.0, size.height - (layoutOffset + child.geometry!.paintExtent));
|
||||
case AxisDirection.right:
|
||||
return Offset(layoutOffset, 0.0);
|
||||
case AxisDirection.down:
|
||||
return Offset(0.0, layoutOffset);
|
||||
case AxisDirection.left:
|
||||
return Offset(size.width - (layoutOffset + child.geometry.paintExtent), 0.0);
|
||||
return Offset(size.width - (layoutOffset + child.geometry!.paintExtent), 0.0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -916,13 +935,13 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
@override
|
||||
List<DiagnosticsNode> debugDescribeChildren() {
|
||||
final List<DiagnosticsNode> children = <DiagnosticsNode>[];
|
||||
RenderSliver child = firstChild;
|
||||
RenderSliver? child = firstChild;
|
||||
if (child == null)
|
||||
return children;
|
||||
|
||||
int count = indexOfFirstChild;
|
||||
while (true) {
|
||||
children.add(child.toDiagnosticsNode(name: labelForChild(count)));
|
||||
children.add(child!.toDiagnosticsNode(name: labelForChild(count)));
|
||||
if (child == lastChild)
|
||||
break;
|
||||
count += 1;
|
||||
|
@ -1043,8 +1062,8 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
|
||||
@override
|
||||
void showOnScreen({
|
||||
RenderObject descendant,
|
||||
Rect rect,
|
||||
RenderObject? descendant,
|
||||
Rect? rect,
|
||||
Duration duration = Duration.zero,
|
||||
Curve curve = Curves.ease,
|
||||
}) {
|
||||
|
@ -1057,7 +1076,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
);
|
||||
}
|
||||
|
||||
final Rect newRect = RenderViewportBase.showInViewport(
|
||||
final Rect? newRect = RenderViewportBase.showInViewport(
|
||||
descendant: descendant,
|
||||
viewport: this,
|
||||
offset: offset,
|
||||
|
@ -1098,11 +1117,11 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||
///
|
||||
/// * [RenderObject.showOnScreen], overridden by [RenderViewportBase] and the
|
||||
/// renderer for [SingleChildScrollView] to delegate to this method.
|
||||
static Rect showInViewport({
|
||||
RenderObject descendant,
|
||||
Rect rect,
|
||||
@required RenderAbstractViewport viewport,
|
||||
@required ViewportOffset offset,
|
||||
static Rect? showInViewport({
|
||||
RenderObject? descendant,
|
||||
Rect? rect,
|
||||
required RenderAbstractViewport viewport,
|
||||
required ViewportOffset offset,
|
||||
Duration duration = Duration.zero,
|
||||
Curve curve = Curves.ease,
|
||||
}) {
|
||||
|
@ -1206,12 +1225,12 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||
/// [new ViewportOffset.zero] or [new ViewportOffset.fixed].
|
||||
RenderViewport({
|
||||
AxisDirection axisDirection = AxisDirection.down,
|
||||
@required AxisDirection crossAxisDirection,
|
||||
@required ViewportOffset offset,
|
||||
required AxisDirection crossAxisDirection,
|
||||
required ViewportOffset offset,
|
||||
double anchor = 0.0,
|
||||
List<RenderSliver> children,
|
||||
RenderSliver center,
|
||||
double cacheExtent,
|
||||
List<RenderSliver>? children,
|
||||
RenderSliver? center,
|
||||
double? cacheExtent,
|
||||
CacheExtentStyle cacheExtentStyle = CacheExtentStyle.pixel,
|
||||
Clip clipBehavior = Clip.hardEdge,
|
||||
}) : assert(anchor != null),
|
||||
|
@ -1302,9 +1321,9 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||
/// the [axisDirection] relative to the [center].
|
||||
///
|
||||
/// The [center] must be a child of the viewport.
|
||||
RenderSliver get center => _center;
|
||||
RenderSliver _center;
|
||||
set center(RenderSliver value) {
|
||||
RenderSliver? get center => _center;
|
||||
RenderSliver? _center;
|
||||
set center(RenderSliver? value) {
|
||||
if (value == _center)
|
||||
return;
|
||||
_center = value;
|
||||
|
@ -1389,8 +1408,8 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||
static const int _maxLayoutCycles = 10;
|
||||
|
||||
// Out-of-band data computed during layout.
|
||||
double _minScrollExtent;
|
||||
double _maxScrollExtent;
|
||||
late double _minScrollExtent;
|
||||
late double _maxScrollExtent;
|
||||
bool _hasVisualOverflow = false;
|
||||
|
||||
@override
|
||||
|
@ -1414,7 +1433,7 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||
offset.applyContentDimensions(0.0, 0.0);
|
||||
return;
|
||||
}
|
||||
assert(center.parent == this);
|
||||
assert(center!.parent == this);
|
||||
|
||||
double mainAxisExtent;
|
||||
double crossAxisExtent;
|
||||
|
@ -1429,7 +1448,7 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||
break;
|
||||
}
|
||||
|
||||
final double centerOffsetAdjustment = center.centerOffsetAdjustment;
|
||||
final double centerOffsetAdjustment = center!.centerOffsetAdjustment;
|
||||
|
||||
double correction;
|
||||
int count = 0;
|
||||
|
@ -1487,24 +1506,24 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||
// to the zero scroll offset (the line between the forward slivers and the
|
||||
// reverse slivers).
|
||||
final double centerOffset = mainAxisExtent * anchor - correctedOffset;
|
||||
final double reverseDirectionRemainingPaintExtent = centerOffset.clamp(0.0, mainAxisExtent) as double;
|
||||
final double forwardDirectionRemainingPaintExtent = (mainAxisExtent - centerOffset).clamp(0.0, mainAxisExtent) as double;
|
||||
final double reverseDirectionRemainingPaintExtent = centerOffset.clamp(0.0, mainAxisExtent);
|
||||
final double forwardDirectionRemainingPaintExtent = (mainAxisExtent - centerOffset).clamp(0.0, mainAxisExtent);
|
||||
|
||||
switch (cacheExtentStyle) {
|
||||
case CacheExtentStyle.pixel:
|
||||
_calculatedCacheExtent = cacheExtent;
|
||||
break;
|
||||
case CacheExtentStyle.viewport:
|
||||
_calculatedCacheExtent = mainAxisExtent * cacheExtent;
|
||||
_calculatedCacheExtent = mainAxisExtent * _cacheExtent;
|
||||
break;
|
||||
}
|
||||
|
||||
final double fullCacheExtent = mainAxisExtent + 2 * _calculatedCacheExtent;
|
||||
final double centerCacheOffset = centerOffset + _calculatedCacheExtent;
|
||||
final double reverseDirectionRemainingCacheExtent = centerCacheOffset.clamp(0.0, fullCacheExtent) as double;
|
||||
final double forwardDirectionRemainingCacheExtent = (fullCacheExtent - centerCacheOffset).clamp(0.0, fullCacheExtent) as double;
|
||||
final double fullCacheExtent = mainAxisExtent + 2 * _calculatedCacheExtent!;
|
||||
final double centerCacheOffset = centerOffset + _calculatedCacheExtent!;
|
||||
final double reverseDirectionRemainingCacheExtent = centerCacheOffset.clamp(0.0, fullCacheExtent);
|
||||
final double forwardDirectionRemainingCacheExtent = (fullCacheExtent - centerCacheOffset).clamp(0.0, fullCacheExtent);
|
||||
|
||||
final RenderSliver leadingNegativeChild = childBefore(center);
|
||||
final RenderSliver? leadingNegativeChild = childBefore(center!);
|
||||
|
||||
if (leadingNegativeChild != null) {
|
||||
// negative scroll offsets
|
||||
|
@ -1519,7 +1538,7 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||
growthDirection: GrowthDirection.reverse,
|
||||
advance: childBefore,
|
||||
remainingCacheExtent: reverseDirectionRemainingCacheExtent,
|
||||
cacheOrigin: (mainAxisExtent - centerOffset).clamp(-_calculatedCacheExtent, 0.0) as double,
|
||||
cacheOrigin: (mainAxisExtent - centerOffset).clamp(-_calculatedCacheExtent!, 0.0),
|
||||
);
|
||||
if (result != 0.0)
|
||||
return -result;
|
||||
|
@ -1537,7 +1556,7 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||
growthDirection: GrowthDirection.forward,
|
||||
advance: childAfter,
|
||||
remainingCacheExtent: forwardDirectionRemainingCacheExtent,
|
||||
cacheOrigin: centerOffset.clamp(-_calculatedCacheExtent, 0.0) as double,
|
||||
cacheOrigin: centerOffset.clamp(-_calculatedCacheExtent!, 0.0),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1578,22 +1597,21 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||
switch (growthDirection) {
|
||||
case GrowthDirection.forward:
|
||||
double scrollOffsetToChild = 0.0;
|
||||
RenderSliver current = center;
|
||||
RenderSliver? current = center;
|
||||
while (current != child) {
|
||||
scrollOffsetToChild += current.geometry.scrollExtent;
|
||||
scrollOffsetToChild += current!.geometry!.scrollExtent;
|
||||
current = childAfter(current);
|
||||
}
|
||||
return scrollOffsetToChild + scrollOffsetWithinChild;
|
||||
case GrowthDirection.reverse:
|
||||
double scrollOffsetToChild = 0.0;
|
||||
RenderSliver current = childBefore(center);
|
||||
RenderSliver? current = childBefore(center!);
|
||||
while (current != child) {
|
||||
scrollOffsetToChild -= current.geometry.scrollExtent;
|
||||
scrollOffsetToChild -= current!.geometry!.scrollExtent;
|
||||
current = childBefore(current);
|
||||
}
|
||||
return scrollOffsetToChild - scrollOffsetWithinChild;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -1604,26 +1622,26 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||
switch (growthDirection) {
|
||||
case GrowthDirection.forward:
|
||||
double pinnedExtent = 0.0;
|
||||
RenderSliver current = center;
|
||||
RenderSliver? current = center;
|
||||
while (current != child) {
|
||||
pinnedExtent += current.geometry.maxScrollObstructionExtent;
|
||||
pinnedExtent += current!.geometry!.maxScrollObstructionExtent;
|
||||
current = childAfter(current);
|
||||
}
|
||||
return pinnedExtent;
|
||||
case GrowthDirection.reverse:
|
||||
double pinnedExtent = 0.0;
|
||||
RenderSliver current = childBefore(center);
|
||||
RenderSliver? current = childBefore(center!);
|
||||
while (current != child) {
|
||||
pinnedExtent += current.geometry.maxScrollObstructionExtent;
|
||||
pinnedExtent += current!.geometry!.maxScrollObstructionExtent;
|
||||
current = childBefore(current);
|
||||
}
|
||||
return pinnedExtent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
void applyPaintTransform(RenderObject child, Matrix4 transform) {
|
||||
// Hit test logic relies on this always providing an invertible matrix.
|
||||
assert(child != null);
|
||||
final SliverPhysicalParentData childParentData = child.parentData as SliverPhysicalParentData;
|
||||
childParentData.applyPaintTransform(transform);
|
||||
|
@ -1640,23 +1658,22 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||
case AxisDirection.right:
|
||||
return parentMainAxisPosition - childParentData.paintOffset.dx;
|
||||
case AxisDirection.up:
|
||||
return child.geometry.paintExtent - (parentMainAxisPosition - childParentData.paintOffset.dy);
|
||||
return child.geometry!.paintExtent - (parentMainAxisPosition - childParentData.paintOffset.dy);
|
||||
case AxisDirection.left:
|
||||
return child.geometry.paintExtent - (parentMainAxisPosition - childParentData.paintOffset.dx);
|
||||
return child.geometry!.paintExtent - (parentMainAxisPosition - childParentData.paintOffset.dx);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
int get indexOfFirstChild {
|
||||
assert(center != null);
|
||||
assert(center.parent == this);
|
||||
assert(center!.parent == this);
|
||||
assert(firstChild != null);
|
||||
int count = 0;
|
||||
RenderSliver child = center;
|
||||
RenderSliver? child = center;
|
||||
while (child != firstChild) {
|
||||
count -= 1;
|
||||
child = childBefore(child);
|
||||
child = childBefore(child!);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -1672,14 +1689,14 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||
Iterable<RenderSliver> get childrenInPaintOrder sync* {
|
||||
if (firstChild == null)
|
||||
return;
|
||||
RenderSliver child = firstChild;
|
||||
RenderSliver? child = firstChild;
|
||||
while (child != center) {
|
||||
yield child;
|
||||
yield child!;
|
||||
child = childAfter(child);
|
||||
}
|
||||
child = lastChild;
|
||||
while (true) {
|
||||
yield child;
|
||||
yield child!;
|
||||
if (child == center)
|
||||
return;
|
||||
child = childBefore(child);
|
||||
|
@ -1690,12 +1707,12 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||
Iterable<RenderSliver> get childrenInHitTestOrder sync* {
|
||||
if (firstChild == null)
|
||||
return;
|
||||
RenderSliver child = center;
|
||||
RenderSliver? child = center;
|
||||
while (child != null) {
|
||||
yield child;
|
||||
child = childAfter(child);
|
||||
}
|
||||
child = childBefore(center);
|
||||
child = childBefore(center!);
|
||||
while (child != null) {
|
||||
yield child;
|
||||
child = childBefore(child);
|
||||
|
@ -1742,10 +1759,10 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
|
|||
/// [new ViewportOffset.zero] or [new ViewportOffset.fixed].
|
||||
RenderShrinkWrappingViewport({
|
||||
AxisDirection axisDirection = AxisDirection.down,
|
||||
@required AxisDirection crossAxisDirection,
|
||||
@required ViewportOffset offset,
|
||||
required AxisDirection crossAxisDirection,
|
||||
required ViewportOffset offset,
|
||||
Clip clipBehavior = Clip.hardEdge,
|
||||
List<RenderSliver> children,
|
||||
List<RenderSliver>? children,
|
||||
}) : super(
|
||||
axisDirection: axisDirection,
|
||||
crossAxisDirection: crossAxisDirection,
|
||||
|
@ -1784,8 +1801,8 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
|
|||
}
|
||||
|
||||
// Out-of-band data computed during layout.
|
||||
double _maxScrollExtent;
|
||||
double _shrinkWrapExtent;
|
||||
late double _maxScrollExtent;
|
||||
late double _shrinkWrapExtent;
|
||||
bool _hasVisualOverflow = false;
|
||||
|
||||
@override
|
||||
|
@ -1881,8 +1898,8 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
|
|||
crossAxisExtent: crossAxisExtent,
|
||||
growthDirection: GrowthDirection.forward,
|
||||
advance: childAfter,
|
||||
remainingCacheExtent: mainAxisExtent + 2 * cacheExtent,
|
||||
cacheOrigin: -cacheExtent,
|
||||
remainingCacheExtent: mainAxisExtent + 2 * _cacheExtent,
|
||||
cacheOrigin: -_cacheExtent,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1908,7 +1925,7 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
|
|||
@override
|
||||
Offset paintOffsetOf(RenderSliver child) {
|
||||
final SliverLogicalParentData childParentData = child.parentData as SliverLogicalParentData;
|
||||
return computeAbsolutePaintOffset(child, childParentData.layoutOffset, GrowthDirection.forward);
|
||||
return computeAbsolutePaintOffset(child, childParentData.layoutOffset!, GrowthDirection.forward);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -1916,9 +1933,9 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
|
|||
assert(child.parent == this);
|
||||
assert(child.constraints.growthDirection == GrowthDirection.forward);
|
||||
double scrollOffsetToChild = 0.0;
|
||||
RenderSliver current = firstChild;
|
||||
RenderSliver? current = firstChild;
|
||||
while (current != child) {
|
||||
scrollOffsetToChild += current.geometry.scrollExtent;
|
||||
scrollOffsetToChild += current!.geometry!.scrollExtent;
|
||||
current = childAfter(current);
|
||||
}
|
||||
return scrollOffsetToChild + scrollOffsetWithinChild;
|
||||
|
@ -1929,9 +1946,9 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
|
|||
assert(child.parent == this);
|
||||
assert(child.constraints.growthDirection == GrowthDirection.forward);
|
||||
double pinnedExtent = 0.0;
|
||||
RenderSliver current = firstChild;
|
||||
RenderSliver? current = firstChild;
|
||||
while (current != child) {
|
||||
pinnedExtent += current.geometry.maxScrollObstructionExtent;
|
||||
pinnedExtent += current!.geometry!.maxScrollObstructionExtent;
|
||||
current = childAfter(current);
|
||||
}
|
||||
return pinnedExtent;
|
||||
|
@ -1939,6 +1956,7 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
|
|||
|
||||
@override
|
||||
void applyPaintTransform(RenderObject child, Matrix4 transform) {
|
||||
// Hit test logic relies on this always providing an invertible matrix.
|
||||
assert(child != null);
|
||||
final Offset offset = paintOffsetOf(child as RenderSliver);
|
||||
transform.translate(offset.dx, offset.dy);
|
||||
|
@ -1953,13 +1971,12 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
|
|||
switch (applyGrowthDirectionToAxisDirection(child.constraints.axisDirection, child.constraints.growthDirection)) {
|
||||
case AxisDirection.down:
|
||||
case AxisDirection.right:
|
||||
return parentMainAxisPosition - childParentData.layoutOffset;
|
||||
return parentMainAxisPosition - childParentData.layoutOffset!;
|
||||
case AxisDirection.up:
|
||||
return (size.height - parentMainAxisPosition) - childParentData.layoutOffset;
|
||||
return (size.height - parentMainAxisPosition) - childParentData.layoutOffset!;
|
||||
case AxisDirection.left:
|
||||
return (size.width - parentMainAxisPosition) - childParentData.layoutOffset;
|
||||
return (size.width - parentMainAxisPosition) - childParentData.layoutOffset!;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -1970,7 +1987,7 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
|
|||
|
||||
@override
|
||||
Iterable<RenderSliver> get childrenInPaintOrder sync* {
|
||||
RenderSliver child = firstChild;
|
||||
RenderSliver? child = firstChild;
|
||||
while (child != null) {
|
||||
yield child;
|
||||
child = childAfter(child);
|
||||
|
@ -1979,7 +1996,7 @@ class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalConta
|
|||
|
||||
@override
|
||||
Iterable<RenderSliver> get childrenInHitTestOrder sync* {
|
||||
RenderSliver child = lastChild;
|
||||
RenderSliver? child = lastChild;
|
||||
while (child != null) {
|
||||
yield child;
|
||||
child = childBefore(child);
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/animation.dart';
|
||||
|
@ -51,7 +49,6 @@ ScrollDirection flipScrollDirection(ScrollDirection direction) {
|
|||
case ScrollDirection.reverse:
|
||||
return ScrollDirection.forward;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Which part of the content inside the viewport should be visible.
|
||||
|
@ -181,8 +178,8 @@ abstract class ViewportOffset extends ChangeNotifier {
|
|||
/// animation, use [jumpTo].
|
||||
Future<void> animateTo(
|
||||
double to, {
|
||||
@required Duration duration,
|
||||
@required Curve curve,
|
||||
required Duration duration,
|
||||
required Curve curve,
|
||||
});
|
||||
|
||||
/// Calls [jumpTo] if duration is null or [Duration.zero], otherwise
|
||||
|
@ -194,9 +191,9 @@ abstract class ViewportOffset extends ChangeNotifier {
|
|||
/// underscroll.
|
||||
Future<void> moveTo(
|
||||
double to, {
|
||||
Duration duration,
|
||||
Curve curve,
|
||||
bool clamp,
|
||||
Duration? duration,
|
||||
Curve? curve,
|
||||
bool? clamp,
|
||||
}) {
|
||||
assert(to != null);
|
||||
if (duration == null || duration == Duration.zero) {
|
||||
|
@ -248,7 +245,7 @@ abstract class ViewportOffset extends ChangeNotifier {
|
|||
/// `super.debugFillDescription(description)`.
|
||||
@mustCallSuper
|
||||
void debugFillDescription(List<String> description) {
|
||||
description.add('offset: ${pixels?.toStringAsFixed(1)}');
|
||||
description.add('offset: ${pixels.toStringAsFixed(1)}');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,8 +277,8 @@ class _FixedViewportOffset extends ViewportOffset {
|
|||
@override
|
||||
Future<void> animateTo(
|
||||
double to, {
|
||||
@required Duration duration,
|
||||
@required Curve curve,
|
||||
required Duration duration,
|
||||
required Curve curve,
|
||||
}) async { }
|
||||
|
||||
@override
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'box.dart';
|
||||
|
@ -111,14 +109,14 @@ class RenderWrap extends RenderBox
|
|||
/// By default, the wrap layout is horizontal and both the children and the
|
||||
/// runs are aligned to the start.
|
||||
RenderWrap({
|
||||
List<RenderBox> children,
|
||||
List<RenderBox>? children,
|
||||
Axis direction = Axis.horizontal,
|
||||
WrapAlignment alignment = WrapAlignment.start,
|
||||
double spacing = 0.0,
|
||||
WrapAlignment runAlignment = WrapAlignment.start,
|
||||
double runSpacing = 0.0,
|
||||
WrapCrossAlignment crossAxisAlignment = WrapCrossAlignment.start,
|
||||
TextDirection textDirection,
|
||||
TextDirection? textDirection,
|
||||
VerticalDirection verticalDirection = VerticalDirection.down,
|
||||
Clip clipBehavior = Clip.none,
|
||||
}) : assert(direction != null),
|
||||
|
@ -292,9 +290,9 @@ class RenderWrap extends RenderBox
|
|||
/// [crossAxisAlignment] is either [WrapCrossAlignment.start] or
|
||||
/// [WrapCrossAlignment.end], or there's more than one child, then the
|
||||
/// [textDirection] must not be null.
|
||||
TextDirection get textDirection => _textDirection;
|
||||
TextDirection _textDirection;
|
||||
set textDirection(TextDirection value) {
|
||||
TextDirection? get textDirection => _textDirection;
|
||||
TextDirection? _textDirection;
|
||||
set textDirection(TextDirection? value) {
|
||||
if (_textDirection != value) {
|
||||
_textDirection = value;
|
||||
markNeedsLayout();
|
||||
|
@ -407,7 +405,7 @@ class RenderWrap extends RenderBox
|
|||
double runWidth = 0.0;
|
||||
double runHeight = 0.0;
|
||||
int childCount = 0;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
// TODO(chunhtai): use the new intrinsic API to calculate child sizes
|
||||
// once https://github.com/flutter/flutter/issues/48679 is fixed.
|
||||
|
@ -437,7 +435,7 @@ class RenderWrap extends RenderBox
|
|||
double runHeight = 0.0;
|
||||
double runWidth = 0.0;
|
||||
int childCount = 0;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
// TODO(chunhtai): use the new intrinsic API to calculate child sizes
|
||||
// once https://github.com/flutter/flutter/issues/48679 is fixed.
|
||||
|
@ -466,7 +464,7 @@ class RenderWrap extends RenderBox
|
|||
switch (direction) {
|
||||
case Axis.horizontal:
|
||||
double width = 0.0;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
width = math.max(width, child.getMinIntrinsicWidth(double.infinity));
|
||||
child = childAfter(child);
|
||||
|
@ -475,7 +473,6 @@ class RenderWrap extends RenderBox
|
|||
case Axis.vertical:
|
||||
return _computeIntrinsicWidthForHeight(height);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -483,7 +480,7 @@ class RenderWrap extends RenderBox
|
|||
switch (direction) {
|
||||
case Axis.horizontal:
|
||||
double width = 0.0;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
width += child.getMaxIntrinsicWidth(double.infinity);
|
||||
child = childAfter(child);
|
||||
|
@ -492,7 +489,6 @@ class RenderWrap extends RenderBox
|
|||
case Axis.vertical:
|
||||
return _computeIntrinsicWidthForHeight(height);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -502,14 +498,13 @@ class RenderWrap extends RenderBox
|
|||
return _computeIntrinsicHeightForWidth(width);
|
||||
case Axis.vertical:
|
||||
double height = 0.0;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
height = math.max(height, child.getMinIntrinsicHeight(double.infinity));
|
||||
child = childAfter(child);
|
||||
}
|
||||
return height;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -519,18 +514,17 @@ class RenderWrap extends RenderBox
|
|||
return _computeIntrinsicHeightForWidth(width);
|
||||
case Axis.vertical:
|
||||
double height = 0.0;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
height += child.getMaxIntrinsicHeight(double.infinity);
|
||||
child = childAfter(child);
|
||||
}
|
||||
return height;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
double? computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
return defaultComputeDistanceToHighestActualBaseline(baseline);
|
||||
}
|
||||
|
||||
|
@ -541,7 +535,6 @@ class RenderWrap extends RenderBox
|
|||
case Axis.vertical:
|
||||
return child.size.height;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double _getCrossAxisExtent(RenderBox child) {
|
||||
|
@ -551,7 +544,6 @@ class RenderWrap extends RenderBox
|
|||
case Axis.vertical:
|
||||
return child.size.width;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
Offset _getOffset(double mainAxisOffset, double crossAxisOffset) {
|
||||
|
@ -561,7 +553,6 @@ class RenderWrap extends RenderBox
|
|||
case Axis.vertical:
|
||||
return Offset(crossAxisOffset, mainAxisOffset);
|
||||
}
|
||||
return Offset.zero;
|
||||
}
|
||||
|
||||
double _getChildCrossAxisOffset(bool flipCrossAxis, double runCrossAxisExtent, double childCrossAxisExtent) {
|
||||
|
@ -574,7 +565,6 @@ class RenderWrap extends RenderBox
|
|||
case WrapCrossAlignment.center:
|
||||
return freeSpace / 2.0;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
bool _hasVisualOverflow = false;
|
||||
|
@ -584,7 +574,7 @@ class RenderWrap extends RenderBox
|
|||
final BoxConstraints constraints = this.constraints;
|
||||
assert(_debugHasNecessaryDirections);
|
||||
_hasVisualOverflow = false;
|
||||
RenderBox child = firstChild;
|
||||
RenderBox? child = firstChild;
|
||||
if (child == null) {
|
||||
size = constraints.smallest;
|
||||
return;
|
||||
|
@ -765,7 +755,7 @@ class RenderWrap extends RenderBox
|
|||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
|
||||
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
|
||||
return defaultHitTestChildren(result, position: position);
|
||||
}
|
||||
|
||||
|
|
|
@ -216,8 +216,8 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
|
|||
/// To use a different [RestorationManager] subclasses can override
|
||||
/// [createRestorationManager], which is called to create the instance
|
||||
/// returned by this getter.
|
||||
RestorationManager get restorationManager => _restorationManager!;
|
||||
RestorationManager? _restorationManager;
|
||||
RestorationManager get restorationManager => _restorationManager;
|
||||
late RestorationManager _restorationManager;
|
||||
|
||||
/// Creates the [RestorationManager] instance available via
|
||||
/// [restorationManager].
|
||||
|
|
|
@ -2677,8 +2677,12 @@ class BuildOwner {
|
|||
e,
|
||||
stack,
|
||||
informationCollector: () sync* {
|
||||
yield DiagnosticsDebugCreator(DebugCreator(_dirtyElements[index]));
|
||||
yield _dirtyElements[index].describeElement('The element being rebuilt at the time was index $index of $dirtyCount');
|
||||
if (index < _dirtyElements.length) {
|
||||
yield DiagnosticsDebugCreator(DebugCreator(_dirtyElements[index]));
|
||||
yield _dirtyElements[index].describeElement('The element being rebuilt at the time was index $index of $dirtyCount');
|
||||
} else {
|
||||
yield ErrorHint('The element being rebuilt at the time was index $index of $dirtyCount, but _dirtyElements only had ${_dirtyElements.length} entries. This suggests some confusion in the framework internals.');
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -201,7 +201,9 @@ class Table extends RenderObjectWidget {
|
|||
/// determine the intrinsic size of the column.
|
||||
///
|
||||
/// The keys of this map (column indexes) are zero-based.
|
||||
final Map<int, TableColumnWidth> columnWidths;
|
||||
///
|
||||
/// If this is set to null, then an empty map is assumed.
|
||||
final Map<int, TableColumnWidth>/*?*/ columnWidths;
|
||||
|
||||
/// How to determine with widths of columns that don't have an explicit sizing
|
||||
/// algorithm.
|
||||
|
|
|
@ -51,6 +51,9 @@ class Viewport extends MultiChildRenderObjectWidget {
|
|||
/// rebuild this widget when the [offset] changes.
|
||||
///
|
||||
/// The [offset] argument must not be null.
|
||||
///
|
||||
/// The [cacheExtent] must be specified if the [cacheExtentStyle] is
|
||||
/// not [CacheExtentStyle.pixel].
|
||||
Viewport({
|
||||
Key key,
|
||||
this.axisDirection = AxisDirection.down,
|
||||
|
@ -117,6 +120,10 @@ class Viewport extends MultiChildRenderObjectWidget {
|
|||
final Key center;
|
||||
|
||||
/// {@macro flutter.rendering.viewport.cacheExtent}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [cacheExtentStyle], which controls the units of the [cacheExtent].
|
||||
final double cacheExtent;
|
||||
|
||||
/// {@macro flutter.rendering.viewport.cacheExtentStyle}
|
||||
|
|
|
@ -1865,7 +1865,7 @@ mixin WidgetInspectorService {
|
|||
|
||||
void _onPaint(RenderObject renderObject) {
|
||||
try {
|
||||
final Element element = renderObject.debugCreator?.element as Element;
|
||||
final Element element = (renderObject.debugCreator as DebugCreator)?.element;
|
||||
if (element is! RenderObjectElement) {
|
||||
// This branch should not hit as long as all RenderObjects were created
|
||||
// by Widgets. It is possible there might be some render objects
|
||||
|
@ -2363,7 +2363,7 @@ class InspectorSelection {
|
|||
set current(RenderObject value) {
|
||||
if (_current != value) {
|
||||
_current = value;
|
||||
_currentElement = value.debugCreator.element as Element;
|
||||
_currentElement = (value.debugCreator as DebugCreator).element;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2384,7 +2384,7 @@ class InspectorSelection {
|
|||
void _computeCurrent() {
|
||||
if (_index < candidates.length) {
|
||||
_current = candidates[index];
|
||||
_currentElement = _current.debugCreator.element as Element;
|
||||
_currentElement = (_current.debugCreator as DebugCreator).element;
|
||||
} else {
|
||||
_current = null;
|
||||
_currentElement = null;
|
||||
|
|
|
@ -391,31 +391,6 @@ void main() {
|
|||
const BoxConstraints viewport = BoxConstraints(maxHeight: 100.0, maxWidth: 100.0);
|
||||
layout(unconstrained, constraints: viewport);
|
||||
|
||||
{
|
||||
FlutterError result;
|
||||
try {
|
||||
unconstrained.getMinIntrinsicWidth(null);
|
||||
} on FlutterError catch (e) {
|
||||
result = e;
|
||||
}
|
||||
expect(result, isNotNull);
|
||||
expect(
|
||||
result.toStringDeep(),
|
||||
equalsIgnoringHashCodes(
|
||||
'FlutterError\n'
|
||||
' The height argument to getMinIntrinsicWidth was null.\n'
|
||||
' The argument to getMinIntrinsicWidth must not be negative or\n'
|
||||
' null.\n'
|
||||
' If you do not have a specific height in mind, then pass\n'
|
||||
' double.infinity instead.\n'
|
||||
),
|
||||
);
|
||||
expect(
|
||||
result.diagnostics.singleWhere((DiagnosticsNode node) => node.level == DiagnosticLevel.hint).toString(),
|
||||
'If you do not have a specific height in mind, then pass double.infinity instead.',
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
FlutterError result;
|
||||
try {
|
||||
|
@ -444,31 +419,6 @@ void main() {
|
|||
);
|
||||
}
|
||||
|
||||
{
|
||||
FlutterError result;
|
||||
try {
|
||||
unconstrained.getMinIntrinsicHeight(null);
|
||||
} on FlutterError catch (e) {
|
||||
result = e;
|
||||
}
|
||||
expect(result, isNotNull);
|
||||
expect(
|
||||
result.toStringDeep(),
|
||||
equalsIgnoringHashCodes(
|
||||
'FlutterError\n'
|
||||
' The width argument to getMinIntrinsicHeight was null.\n'
|
||||
' The argument to getMinIntrinsicHeight must not be negative or\n'
|
||||
' null.\n'
|
||||
' If you do not have a specific width in mind, then pass\n'
|
||||
' double.infinity instead.\n'
|
||||
),
|
||||
);
|
||||
expect(
|
||||
result.diagnostics.singleWhere((DiagnosticsNode node) => node.level == DiagnosticLevel.hint).toString(),
|
||||
'If you do not have a specific width in mind, then pass double.infinity instead.',
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
FlutterError result;
|
||||
try {
|
||||
|
@ -497,31 +447,6 @@ void main() {
|
|||
);
|
||||
}
|
||||
|
||||
{
|
||||
FlutterError result;
|
||||
try {
|
||||
unconstrained.getMaxIntrinsicWidth(null);
|
||||
} on FlutterError catch (e) {
|
||||
result = e;
|
||||
}
|
||||
expect(result, isNotNull);
|
||||
expect(
|
||||
result.toStringDeep(),
|
||||
equalsIgnoringHashCodes(
|
||||
'FlutterError\n'
|
||||
' The height argument to getMaxIntrinsicWidth was null.\n'
|
||||
' The argument to getMaxIntrinsicWidth must not be negative or\n'
|
||||
' null.\n'
|
||||
' If you do not have a specific height in mind, then pass\n'
|
||||
' double.infinity instead.\n'
|
||||
),
|
||||
);
|
||||
expect(
|
||||
result.diagnostics.singleWhere((DiagnosticsNode node) => node.level == DiagnosticLevel.hint).toString(),
|
||||
'If you do not have a specific height in mind, then pass double.infinity instead.',
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
FlutterError result;
|
||||
try {
|
||||
|
@ -550,31 +475,6 @@ void main() {
|
|||
);
|
||||
}
|
||||
|
||||
{
|
||||
FlutterError result;
|
||||
try {
|
||||
unconstrained.getMaxIntrinsicHeight(null);
|
||||
} on FlutterError catch (e) {
|
||||
result = e;
|
||||
}
|
||||
expect(result, isNotNull);
|
||||
expect(
|
||||
result.toStringDeep(),
|
||||
equalsIgnoringHashCodes(
|
||||
'FlutterError\n'
|
||||
' The width argument to getMaxIntrinsicHeight was null.\n'
|
||||
' The argument to getMaxIntrinsicHeight must not be negative or\n'
|
||||
' null.\n'
|
||||
' If you do not have a specific width in mind, then pass\n'
|
||||
' double.infinity instead.\n'
|
||||
),
|
||||
);
|
||||
expect(
|
||||
result.diagnostics.singleWhere((DiagnosticsNode node) => node.level == DiagnosticLevel.hint).toString(),
|
||||
'If you do not have a specific width in mind, then pass double.infinity instead.',
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
FlutterError result;
|
||||
try {
|
||||
|
@ -733,7 +633,7 @@ void main() {
|
|||
|
||||
bool isHit = result.addWithPaintTransform(
|
||||
transform: null,
|
||||
position: null,
|
||||
position: Offset.zero,
|
||||
hitTest: (BoxHitTestResult result, Offset position) {
|
||||
expect(result, isNotNull);
|
||||
positions.add(position);
|
||||
|
@ -741,12 +641,12 @@ void main() {
|
|||
},
|
||||
);
|
||||
expect(isHit, isTrue);
|
||||
expect(positions.single, isNull);
|
||||
expect(positions.single, Offset.zero);
|
||||
positions.clear();
|
||||
|
||||
isHit = result.addWithPaintTransform(
|
||||
transform: Matrix4.translationValues(20, 30, 0),
|
||||
position: null,
|
||||
position: Offset.zero,
|
||||
hitTest: (BoxHitTestResult result, Offset position) {
|
||||
expect(result, isNotNull);
|
||||
positions.add(position);
|
||||
|
@ -754,7 +654,7 @@ void main() {
|
|||
},
|
||||
);
|
||||
expect(isHit, isTrue);
|
||||
expect(positions.single, isNull);
|
||||
expect(positions.single, const Offset(-20.0, -30.0));
|
||||
positions.clear();
|
||||
|
||||
const Offset position = Offset(3, 4);
|
||||
|
@ -817,7 +717,7 @@ void main() {
|
|||
|
||||
bool isHit = result.addWithPaintOffset(
|
||||
offset: null,
|
||||
position: null,
|
||||
position: Offset.zero,
|
||||
hitTest: (BoxHitTestResult result, Offset position) {
|
||||
expect(result, isNotNull);
|
||||
positions.add(position);
|
||||
|
@ -825,12 +725,12 @@ void main() {
|
|||
},
|
||||
);
|
||||
expect(isHit, isTrue);
|
||||
expect(positions.single, isNull);
|
||||
expect(positions.single, Offset.zero);
|
||||
positions.clear();
|
||||
|
||||
isHit = result.addWithPaintOffset(
|
||||
offset: const Offset(55, 32),
|
||||
position: null,
|
||||
position: Offset.zero,
|
||||
hitTest: (BoxHitTestResult result, Offset position) {
|
||||
expect(result, isNotNull);
|
||||
positions.add(position);
|
||||
|
@ -838,7 +738,7 @@ void main() {
|
|||
},
|
||||
);
|
||||
expect(isHit, isTrue);
|
||||
expect(positions.single, isNull);
|
||||
expect(positions.single, const Offset(-55.0, -32.0));
|
||||
positions.clear();
|
||||
|
||||
const Offset position = Offset(3, 4);
|
||||
|
@ -888,7 +788,7 @@ void main() {
|
|||
|
||||
bool isHit = result.addWithRawTransform(
|
||||
transform: null,
|
||||
position: null,
|
||||
position: Offset.zero,
|
||||
hitTest: (BoxHitTestResult result, Offset position) {
|
||||
expect(result, isNotNull);
|
||||
positions.add(position);
|
||||
|
@ -896,12 +796,12 @@ void main() {
|
|||
},
|
||||
);
|
||||
expect(isHit, isTrue);
|
||||
expect(positions.single, isNull);
|
||||
expect(positions.single, Offset.zero);
|
||||
positions.clear();
|
||||
|
||||
isHit = result.addWithRawTransform(
|
||||
transform: Matrix4.translationValues(20, 30, 0),
|
||||
position: null,
|
||||
position: Offset.zero,
|
||||
hitTest: (BoxHitTestResult result, Offset position) {
|
||||
expect(result, isNotNull);
|
||||
positions.add(position);
|
||||
|
@ -909,7 +809,7 @@ void main() {
|
|||
},
|
||||
);
|
||||
expect(isHit, isTrue);
|
||||
expect(positions.single, isNull);
|
||||
expect(positions.single, const Offset(20.0, 30.0));
|
||||
positions.clear();
|
||||
|
||||
const Offset position = Offset(3, 4);
|
||||
|
@ -953,6 +853,82 @@ void main() {
|
|||
positions.clear();
|
||||
});
|
||||
|
||||
test('addWithOutOfBandPosition', () {
|
||||
final BoxHitTestResult result = BoxHitTestResult();
|
||||
bool ran = false;
|
||||
|
||||
bool isHit = result.addWithOutOfBandPosition(
|
||||
paintOffset: const Offset(20, 30),
|
||||
hitTest: (BoxHitTestResult result) {
|
||||
expect(result, isNotNull);
|
||||
ran = true;
|
||||
return true;
|
||||
},
|
||||
);
|
||||
expect(isHit, isTrue);
|
||||
expect(ran, isTrue);
|
||||
ran = false;
|
||||
|
||||
isHit = result.addWithOutOfBandPosition(
|
||||
paintTransform: Matrix4.translationValues(20, 30, 0),
|
||||
hitTest: (BoxHitTestResult result) {
|
||||
expect(result, isNotNull);
|
||||
ran = true;
|
||||
return true;
|
||||
},
|
||||
);
|
||||
expect(isHit, isTrue);
|
||||
expect(ran, isTrue);
|
||||
ran = false;
|
||||
|
||||
isHit = result.addWithOutOfBandPosition(
|
||||
rawTransform: Matrix4.translationValues(20, 30, 0),
|
||||
hitTest: (BoxHitTestResult result) {
|
||||
expect(result, isNotNull);
|
||||
ran = true;
|
||||
return true;
|
||||
},
|
||||
);
|
||||
expect(isHit, isTrue);
|
||||
expect(ran, isTrue);
|
||||
ran = false;
|
||||
|
||||
isHit = result.addWithOutOfBandPosition(
|
||||
rawTransform: MatrixUtils.forceToPoint(Offset.zero), // cannot be inverted
|
||||
hitTest: (BoxHitTestResult result) {
|
||||
expect(result, isNotNull);
|
||||
ran = true;
|
||||
return true;
|
||||
},
|
||||
);
|
||||
expect(isHit, isTrue);
|
||||
expect(ran, isTrue);
|
||||
ran = false;
|
||||
|
||||
try {
|
||||
isHit = result.addWithOutOfBandPosition(
|
||||
paintTransform: MatrixUtils.forceToPoint(Offset.zero), // cannot be inverted
|
||||
hitTest: (BoxHitTestResult result) {
|
||||
fail('non-invertible transform should be caught');
|
||||
},
|
||||
);
|
||||
fail('no exception thrown');
|
||||
} on AssertionError catch (e) {
|
||||
expect(e.message, 'paintTransform must be invertible.');
|
||||
}
|
||||
|
||||
try {
|
||||
isHit = result.addWithOutOfBandPosition(
|
||||
hitTest: (BoxHitTestResult result) {
|
||||
fail('addWithOutOfBandPosition should need some transformation of some sort');
|
||||
},
|
||||
);
|
||||
fail('no exception thrown');
|
||||
} on AssertionError catch (e) {
|
||||
expect(e.message, 'Exactly one transform or offset argument must be provided.');
|
||||
}
|
||||
});
|
||||
|
||||
test('error message', () {
|
||||
{
|
||||
final RenderBox renderObject = RenderConstrainedBox(
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:ui' as ui show window;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import '../flutter_test_alternative.dart';
|
||||
|
@ -46,7 +48,7 @@ void main() {
|
|||
expect(offscreen.child.hasSize, isFalse);
|
||||
expect(offscreen.painted, isFalse);
|
||||
// Attach the offscreen to a custom render view and owner
|
||||
final RenderView renderView = RenderView(configuration: testConfiguration, window: null);
|
||||
final RenderView renderView = RenderView(configuration: testConfiguration, window: ui.window);
|
||||
final PipelineOwner pipelineOwner = PipelineOwner();
|
||||
renderView.attach(pipelineOwner);
|
||||
renderView.child = offscreen.root;
|
||||
|
@ -76,7 +78,7 @@ void main() {
|
|||
expect(offscreen.child.hasSize, isFalse);
|
||||
expect(offscreen.painted, isFalse);
|
||||
// Attach the offscreen to a custom render view and owner
|
||||
final RenderView renderView = RenderView(configuration: testConfiguration, window: null);
|
||||
final RenderView renderView = RenderView(configuration: testConfiguration, window: ui.window);
|
||||
final PipelineOwner pipelineOwner = PipelineOwner();
|
||||
renderView.attach(pipelineOwner);
|
||||
renderView.child = offscreen.root;
|
||||
|
|
|
@ -47,7 +47,7 @@ void main() {
|
|||
for (final HitTestTarget target in annotationFinder(position)) {
|
||||
result.addWithRawTransform(
|
||||
transform: Matrix4.identity(),
|
||||
position: null,
|
||||
position: position,
|
||||
hitTest: (BoxHitTestResult result, Offset position) {
|
||||
result.add(HitTestEntry(target));
|
||||
return true;
|
||||
|
|
|
@ -32,7 +32,7 @@ void main() {
|
|||
for (final TestAnnotationEntry entry in annotationFinder(position)) {
|
||||
result.addWithRawTransform(
|
||||
transform: entry.transform,
|
||||
position: null,
|
||||
position: position,
|
||||
hitTest: (BoxHitTestResult result, Offset position) {
|
||||
result.add(entry);
|
||||
return true;
|
||||
|
|
|
@ -30,7 +30,7 @@ void main() {
|
|||
expect(transform, Matrix4.zero());
|
||||
|
||||
final BoxHitTestResult hitTestResult = BoxHitTestResult();
|
||||
expect(fittedBox.hitTestChildren(hitTestResult), isFalse);
|
||||
expect(fittedBox.hitTestChildren(hitTestResult, position: Offset.zero), isFalse);
|
||||
});
|
||||
|
||||
test('RenderFittedBox does not paint with empty sizes', () {
|
||||
|
|
|
@ -343,8 +343,6 @@ void main() {
|
|||
expect(candidate.keepAlive, isFalse);
|
||||
expect(candidate.index, isNull);
|
||||
expect(candidate.toString(), 'index=null; layoutOffset=None');
|
||||
candidate.keepAlive = null;
|
||||
expect(candidate.toString(), 'index=null; layoutOffset=None');
|
||||
candidate.keepAlive = true;
|
||||
expect(candidate.toString(), 'index=null; keepAlive; layoutOffset=None');
|
||||
candidate.keepAlive = false;
|
||||
|
|
|
@ -134,18 +134,6 @@ class NonExistentPositionDelegate extends MultiChildLayoutDelegate {
|
|||
bool shouldRelayout(MultiChildLayoutDelegate oldDelegate) => true;
|
||||
}
|
||||
|
||||
// Used in the 'performLayout error control test' test case
|
||||
// to trigger an error when positioning with null offset
|
||||
class NullOffsetPositionDelegate extends MultiChildLayoutDelegate {
|
||||
@override
|
||||
void performLayout(Size size) {
|
||||
positionChild(0, null);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRelayout(MultiChildLayoutDelegate oldDelegate) => true;
|
||||
}
|
||||
|
||||
// Used in the 'performLayout error control test' test case for triggering
|
||||
// to layout child more than once
|
||||
class InvalidConstraintsChildLayoutDelegate extends MultiChildLayoutDelegate {
|
||||
|
@ -371,17 +359,6 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('positionChild on non existent child', (WidgetTester tester) async {
|
||||
expectFlutterErrorMessage(
|
||||
tester: tester,
|
||||
delegate: NullOffsetPositionDelegate(),
|
||||
message:
|
||||
'FlutterError\n'
|
||||
' The NullOffsetPositionDelegate custom multichild layout delegate\n'
|
||||
' provided a null position for the child with id "0".\n',
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets("_callPerformLayout on child that doesn't have id", (WidgetTester tester) async {
|
||||
expectFlutterErrorMessage(
|
||||
widget: Center(
|
||||
|
|
|
@ -138,48 +138,6 @@ void main() {
|
|||
expect(error.toStringDeep(), contains('2 more times'));
|
||||
});
|
||||
|
||||
testWidgets('assembleSemanticsNode throws FlutterError', (WidgetTester tester) async {
|
||||
final List<String> log = <String>[];
|
||||
final GlobalKey target = GlobalKey();
|
||||
await tester.pumpWidget(CustomPaint(
|
||||
key: target,
|
||||
isComplex: true,
|
||||
painter: TestCustomPainter(log: log),
|
||||
));
|
||||
final RenderCustomPaint renderCustom = target.currentContext.findRenderObject() as RenderCustomPaint;
|
||||
dynamic error;
|
||||
try {
|
||||
renderCustom.assembleSemanticsNode(
|
||||
null,
|
||||
null,
|
||||
<SemanticsNode>[SemanticsNode()],
|
||||
);
|
||||
} on FlutterError catch (e) {
|
||||
error = e;
|
||||
}
|
||||
expect(error, isNotNull);
|
||||
expect(error.toStringDeep(), equalsIgnoringHashCodes(
|
||||
'FlutterError\n'
|
||||
' RenderCustomPaint does not have a child widget but received a\n'
|
||||
' non-empty list of child SemanticsNode:\n'
|
||||
' SemanticsNode#1(Rect.fromLTRB(0.0, 0.0, 0.0, 0.0), invisible)\n'
|
||||
));
|
||||
|
||||
await tester.pumpWidget(CustomPaint(
|
||||
key: target,
|
||||
isComplex: true,
|
||||
painter: TestCustomPainterWithCustomSemanticsBuilder(),
|
||||
));
|
||||
final dynamic exception = tester.takeException();
|
||||
expect(exception, isFlutterError);
|
||||
error = exception;
|
||||
expect(error.toStringDeep(), equalsIgnoringHashCodes(
|
||||
'FlutterError\n'
|
||||
' Failed to update the list of CustomPainterSemantics:\n'
|
||||
" - duplicate key [<'0'>] found at position 1\n"
|
||||
));
|
||||
});
|
||||
|
||||
testWidgets('CustomPaint sizing', (WidgetTester tester) async {
|
||||
final GlobalKey target = GlobalKey();
|
||||
|
||||
|
|
|
@ -379,7 +379,7 @@ class TestAutomatedTestWidgetsFlutterBinding extends AutomatedTestWidgetsFlutter
|
|||
|
||||
@override
|
||||
TestRestorationManager createRestorationManager() {
|
||||
return null;
|
||||
return TestRestorationManager();
|
||||
}
|
||||
|
||||
int _deferred = 0;
|
||||
|
|
|
@ -745,7 +745,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
|
|||
service.setSelection(elementB.renderObject);
|
||||
expect(selectionChangedCount, equals(2));
|
||||
expect(service.selection.current, equals(elementB.renderObject));
|
||||
expect(service.selection.currentElement, equals(elementB.renderObject.debugCreator.element));
|
||||
expect(service.selection.currentElement, equals((elementB.renderObject.debugCreator as DebugCreator).element));
|
||||
|
||||
service.setSelection('invalid selection');
|
||||
expect(selectionChangedCount, equals(2));
|
||||
|
@ -1186,7 +1186,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
|
|||
service.setSelection(elementB.renderObject);
|
||||
expect(selectionChangedCount, equals(2));
|
||||
expect(service.selection.current, equals(elementB.renderObject));
|
||||
expect(service.selection.currentElement, equals(elementB.renderObject.debugCreator.element));
|
||||
expect(service.selection.currentElement, equals((elementB.renderObject.debugCreator as DebugCreator).element));
|
||||
|
||||
service.setSelection('invalid selection');
|
||||
expect(selectionChangedCount, equals(2));
|
||||
|
|
|
@ -759,6 +759,7 @@ abstract class WidgetController {
|
|||
PointerDeviceKind kind = PointerDeviceKind.touch,
|
||||
int buttons = kPrimaryButton,
|
||||
}) async {
|
||||
assert(downLocation != null);
|
||||
final TestGesture result = await createGesture(
|
||||
pointer: pointer,
|
||||
kind: kind,
|
||||
|
|
|
@ -818,6 +818,7 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
|
|||
|
||||
@override
|
||||
HitTestResult hitTestOnBinding(Offset location) {
|
||||
assert(location != null);
|
||||
location = binding.localToGlobal(location);
|
||||
return super.hitTestOnBinding(location);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue