migrate rendering to nullsafety (#64621)

This commit is contained in:
Ian Hickson 2020-08-27 16:38:10 -07:00 committed by GitHub
parent dcdee4bb0d
commit 8a6a76a334
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
67 changed files with 2987 additions and 3053 deletions

View file

@ -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

View file

@ -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

View file

@ -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`.

View file

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

View file

@ -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

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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;

View file

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

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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));

View file

@ -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,

View file

@ -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,
),

View file

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

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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);
}

View file

@ -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,
}) {

View file

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

View file

@ -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

View file

@ -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)

View file

@ -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';

View file

@ -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

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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();

View file

@ -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!);
}
}

View file

@ -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!);
}
}

View file

@ -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);

View file

@ -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(

View file

@ -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;

View file

@ -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,
));

View file

@ -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;

View file

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

View file

@ -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!);
},
);
}

View file

@ -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));

View file

@ -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);

View file

@ -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,

View file

@ -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);
}

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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);
}

View file

@ -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].

View file

@ -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.');
}
},
);
}

View file

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

View file

@ -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}

View file

@ -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;

View file

@ -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(

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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', () {

View file

@ -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;

View file

@ -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(

View file

@ -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();

View file

@ -379,7 +379,7 @@ class TestAutomatedTestWidgetsFlutterBinding extends AutomatedTestWidgetsFlutter
@override
TestRestorationManager createRestorationManager() {
return null;
return TestRestorationManager();
}
int _deferred = 0;

View file

@ -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));

View file

@ -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,

View file

@ -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);
}