Unverified Commit 8a6a76a3 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

migrate rendering to nullsafety (#64621)

parent dcdee4bb
......@@ -202,6 +202,7 @@ linter:
- use_full_hex_values_for_flutter_colors
# - use_function_type_syntax_for_parameters # not yet tested
# - use_key_in_widget_constructors # not yet tested
- use_late_for_private_fields_and_variables
- use_rethrow_when_possible
# - use_setters_to_change_properties # not yet tested
# - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182
......
......@@ -8,5 +8,6 @@ analyzer:
errors:
always_require_non_null_named_parameters: false # not needed with nnbd
type_init_formals: false # https://github.com/dart-lang/linter/issues/2192
unrelated_type_equality_checks: false # https://github.com/dart-lang/linter/issues/2196
void_checks: false # https://github.com/dart-lang/linter/issues/2185
unnecessary_null_comparison: false # https://github.com/dart-lang/language/issues/1018 , turned off until https://github.com/flutter/flutter/issues/61042
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
/// The Flutter rendering tree.
///
/// To use, import `package:flutter/rendering.dart`.
......
......@@ -208,6 +208,20 @@ class _ChainedEvaluation<T> extends Animatable<T> {
/// [Tween]s that use dedicated `lerp` methods instead of merely relying on the
/// operators (in particular, this allows them to handle null values in a more
/// useful manner).
///
/// ## Nullability
///
/// The [begin] and [end] fields are nullable; a [Tween] does not have to
/// have non-null values specified when it is created.
///
/// If `T` is nullable, then [lerp] and [transform] may return null.
/// This is typically seen in the case where [begin] is null and `t`
/// is 0.0, or [end] is null and `t` is 1.0, or both are null (at any
/// `t` value).
///
/// If `T` is not nullable, then [begin] and [end] must both be set to
/// non-null values before using [lerp] or [transform], otherwise they
/// will throw.
class Tween<T extends dynamic> extends Animatable<T> {
/// Creates a tween.
///
......@@ -236,6 +250,9 @@ class Tween<T extends dynamic> extends Animatable<T> {
/// The default implementation of this method uses the [+], [-], and [*]
/// operators on `T`. The [begin] and [end] properties must therefore be
/// non-null by the time this method is called.
///
/// In general, however, it is possible for this to return null, especially
/// when `t`=0.0 and [begin] is null, or `t`=1.0 and [end] is null.
@protected
T lerp(double t) {
assert(begin != null);
......@@ -291,6 +308,9 @@ class ReverseTween<T> extends Tween<T> {
/// This class specializes the interpolation of [Tween<Color>] to use
/// [Color.lerp].
///
/// The values can be null, representing no color (which is distinct to
/// transparent black, as represented by [Colors.transparent]).
///
/// See [Tween] for a discussion on how to use interpolation objects.
class ColorTween extends Tween<Color?> {
/// Creates a [Color] tween.
......@@ -314,6 +334,8 @@ class ColorTween extends Tween<Color?> {
/// This class specializes the interpolation of [Tween<Size>] to use
/// [Size.lerp].
///
/// The values can be null, representing [Size.zero].
///
/// See [Tween] for a discussion on how to use interpolation objects.
class SizeTween extends Tween<Size?> {
/// Creates a [Size] tween.
......@@ -332,6 +354,9 @@ class SizeTween extends Tween<Size?> {
/// This class specializes the interpolation of [Tween<Rect>] to use
/// [Rect.lerp].
///
/// The values can be null, representing a zero-sized rectangle at the
/// origin ([Rect.zero]).
///
/// See [Tween] for a discussion on how to use interpolation objects.
class RectTween extends Tween<Rect?> {
/// Creates a [Rect] tween.
......@@ -355,6 +380,9 @@ class RectTween extends Tween<Rect?> {
/// This is the closest approximation to a linear tween that is possible with an
/// integer. Compare to [StepTween] and [Tween<double>].
///
/// The [begin] and [end] values must be set to non-null values before
/// calling [lerp] or [transform].
///
/// See [Tween] for a discussion on how to use interpolation objects.
class IntTween extends Tween<int> {
/// Creates an int tween.
......@@ -380,6 +408,9 @@ class IntTween extends Tween<int> {
/// This results in a value that is never greater than the equivalent
/// value from a linear double interpolation. Compare to [IntTween].
///
/// The [begin] and [end] values must be set to non-null values before
/// calling [lerp] or [transform].
///
/// See [Tween] for a discussion on how to use interpolation objects.
class StepTween extends Tween<int> {
/// Creates an [int] tween that floors.
......
......@@ -3377,13 +3377,10 @@ abstract class DiagnosticableTree with Diagnosticable {
///
/// * [toString], for a brief description of the object.
/// * [toStringDeep], for a description of the subtree rooted at this object.
String? toStringShallow({
String toStringShallow({
String joiner = ', ',
DiagnosticLevel minLevel = DiagnosticLevel.debug,
}) {
if (kReleaseMode) {
return toString();
}
String? shallowString;
assert(() {
final StringBuffer result = StringBuffer();
......@@ -3398,7 +3395,7 @@ abstract class DiagnosticableTree with Diagnosticable {
shallowString = result.toString();
return true;
}());
return shallowString;
return shallowString ?? toString();
}
/// Returns a string representation of this node and its descendants.
......@@ -3470,13 +3467,10 @@ mixin DiagnosticableTreeMixin implements DiagnosticableTree {
}
@override
String? toStringShallow({
String toStringShallow({
String joiner = ', ',
DiagnosticLevel minLevel = DiagnosticLevel.debug,
}) {
if (kReleaseMode) {
return toString();
}
String? shallowString;
assert(() {
final StringBuffer result = StringBuffer();
......@@ -3491,7 +3485,7 @@ mixin DiagnosticableTreeMixin implements DiagnosticableTree {
shallowString = result.toString();
return true;
}());
return shallowString;
return shallowString ?? toString();
}
@override
......
......@@ -291,6 +291,7 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
event is PointerHoverEvent ||
event is PointerAddedEvent ||
event is PointerRemovedEvent) {
assert(event.position != null);
dispatchEvent(event, hitTestResult);
}
}
......
......@@ -48,6 +48,7 @@ class PointerEventConverter {
static Iterable<PointerEvent> expand(Iterable<ui.PointerData> data, double devicePixelRatio) sync* {
for (final ui.PointerData datum in data) {
final Offset position = Offset(datum.physicalX, datum.physicalY) / devicePixelRatio;
assert(position != null);
final Offset delta = Offset(datum.physicalDeltaX, datum.physicalDeltaY) / devicePixelRatio;
final double radiusMinor = _toLogicalPixels(datum.radiusMinor, devicePixelRatio);
final double radiusMajor = _toLogicalPixels(datum.radiusMajor, devicePixelRatio);
......
......@@ -44,6 +44,9 @@ class PlaceholderDimensions {
}) : assert(size != null),
assert(alignment != null);
/// A constant representing an empty placeholder.
static const PlaceholderDimensions empty = PlaceholderDimensions(size: Size.zero, alignment: ui.PlaceholderAlignment.bottom);
/// Width and height dimensions of the placeholder.
final Size size;
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/animation.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/scheduler.dart';
......@@ -76,13 +74,13 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
/// The arguments [duration], [curve], [alignment], and [vsync] must
/// not be null.
RenderAnimatedSize({
@required TickerProvider vsync,
@required Duration duration,
Duration reverseDuration,
required TickerProvider vsync,
required Duration duration,
Duration? reverseDuration,
Curve curve = Curves.linear,
AlignmentGeometry alignment = Alignment.center,
TextDirection textDirection,
RenderBox child,
TextDirection? textDirection,
RenderBox? child,
}) : assert(vsync != null),
assert(duration != null),
assert(curve != null),
......@@ -102,11 +100,11 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
);
}
AnimationController _controller;
CurvedAnimation _animation;
late final AnimationController _controller;
late final CurvedAnimation _animation;
final SizeTween _sizeTween = SizeTween();
bool _hasVisualOverflow;
double _lastValue;
late bool _hasVisualOverflow;
double? _lastValue;
/// The state this size animation is in.
///
......@@ -116,7 +114,7 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
RenderAnimatedSizeState _state = RenderAnimatedSizeState.start;
/// The duration of the animation.
Duration get duration => _controller.duration;
Duration get duration => _controller.duration!;
set duration(Duration value) {
assert(value != null);
if (value == _controller.duration)
......@@ -125,8 +123,8 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
}
/// The duration of the animation when running in reverse.
Duration get reverseDuration => _controller.reverseDuration;
set reverseDuration(Duration value) {
Duration? get reverseDuration => _controller.reverseDuration;
set reverseDuration(Duration? value) {
if (value == _controller.reverseDuration)
return;
_controller.reverseDuration = value;
......@@ -164,7 +162,7 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
super.detach();
}
Size get _animatedSize {
Size? get _animatedSize {
return _sizeTween.evaluate(_animation);
}
......@@ -181,7 +179,7 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
return;
}
child.layout(constraints, parentUsesSize: true);
child!.layout(constraints, parentUsesSize: true);
assert(_state != null);
switch (_state) {
......@@ -199,11 +197,11 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
break;
}
size = constraints.constrain(_animatedSize);
size = constraints.constrain(_animatedSize!);
alignChild();
if (size.width < _sizeTween.end.width ||
size.height < _sizeTween.end.height)
if (size.width < _sizeTween.end!.width ||
size.height < _sizeTween.end!.height)
_hasVisualOverflow = true;
}
......@@ -217,7 +215,7 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
/// We have the initial size to animate from, but we do not have the target
/// size to animate to, so we set both ends to child's size.
void _layoutStart() {
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child.size);
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child!.size);
_state = RenderAnimatedSizeState.stable;
}
......@@ -227,14 +225,14 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
/// If during animation the size of the child changes we restart the
/// animation.
void _layoutStable() {
if (_sizeTween.end != child.size) {
if (_sizeTween.end != child!.size) {
_sizeTween.begin = size;
_sizeTween.end = debugAdoptSize(child.size);
_sizeTween.end = debugAdoptSize(child!.size);
_restartAnimation();
_state = RenderAnimatedSizeState.changed;
} else if (_controller.value == _controller.upperBound) {
// Animation finished. Reset target sizes.
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child.size);
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child!.size);
} else if (!_controller.isAnimating) {
_controller.forward(); // resume the animation after being detached
}
......@@ -247,9 +245,9 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
/// changes again, we match the child's size, restart animation and go to
/// unstable state.
void _layoutChanged() {
if (_sizeTween.end != child.size) {
if (_sizeTween.end != child!.size) {
// Child size changed again. Match the child's size and restart animation.
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child.size);
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child!.size);
_restartAnimation();
_state = RenderAnimatedSizeState.unstable;
} else {
......@@ -264,9 +262,9 @@ class RenderAnimatedSize extends RenderAligningShiftedBox {
///
/// Continue tracking the child's size until is stabilizes.
void _layoutUnstable() {
if (_sizeTween.end != child.size) {
if (_sizeTween.end != child!.size) {
// Still unstable. Continue tracking the child.
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child.size);
_sizeTween.begin = _sizeTween.end = debugAdoptSize(child!.size);
_restartAnimation();
} else {
// Child size stabilized.
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'dart:developer';
import 'dart:typed_data';
......@@ -50,8 +48,8 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
}
/// The current [RendererBinding], if one has been created.
static RendererBinding get instance => _instance;
static RendererBinding _instance;
static RendererBinding? get instance => _instance;
static RendererBinding? _instance;
@override
void initServiceExtensions() {
......@@ -145,20 +143,25 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
///
/// Called automatically when the binding is created.
void initRenderView() {
assert(renderView == null);
assert(!_debugIsRenderViewInitialized);
assert(() {
_debugIsRenderViewInitialized = true;
return true;
}());
renderView = RenderView(configuration: createViewConfiguration(), window: window);
renderView.prepareInitialFrame();
}
bool _debugIsRenderViewInitialized = false;
/// The object that manages state about currently connected mice, for hover
/// notification.
MouseTracker get mouseTracker => _mouseTracker;
MouseTracker _mouseTracker;
MouseTracker get mouseTracker => _mouseTracker!;
MouseTracker? _mouseTracker;
/// The render tree's owner, which maintains dirty state for layout,
/// composite, paint, and accessibility semantics.
PipelineOwner get pipelineOwner => _pipelineOwner;
PipelineOwner _pipelineOwner;
late PipelineOwner _pipelineOwner;
/// The render tree that's attached to the output surface.
RenderView get renderView => _pipelineOwner.rootNode as RenderView;
......@@ -239,25 +242,26 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
);
}
SemanticsHandle _semanticsHandle;
SemanticsHandle? _semanticsHandle;
/// Creates a [MouseTracker] which manages state about currently connected
/// mice, for hover notification.
///
/// Used by testing framework to reinitialize the mouse tracker between tests.
@visibleForTesting
void initMouseTracker([MouseTracker tracker]) {
void initMouseTracker([MouseTracker? tracker]) {
_mouseTracker?.dispose();
_mouseTracker = tracker ?? MouseTracker();
}
@override // from GestureBinding
void dispatchEvent(PointerEvent event, HitTestResult hitTestResult) {
void dispatchEvent(PointerEvent event, HitTestResult? hitTestResult) {
if (hitTestResult != null ||
event is PointerHoverEvent ||
event is PointerAddedEvent ||
event is PointerRemovedEvent) {
_mouseTracker.updateWithEvent(event,
assert(event.position != null);
_mouseTracker!.updateWithEvent(event,
() => hitTestResult ?? renderView.hitTestMouseTrackers(event.position));
}
super.dispatchEvent(event, hitTestResult);
......@@ -278,7 +282,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
}
}
void _handleSemanticsAction(int id, SemanticsAction action, ByteData args) {
void _handleSemanticsAction(int id, SemanticsAction action, ByteData? args) {
_pipelineOwner.semanticsOwner?.performAction(
id,
action,
......@@ -306,13 +310,13 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
_debugMouseTrackerUpdateScheduled = true;
return true;
}());
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
SchedulerBinding.instance!.addPostFrameCallback((Duration duration) {
assert(_debugMouseTrackerUpdateScheduled);
assert(() {
_debugMouseTrackerUpdateScheduled = false;
return true;
}());
_mouseTracker.updateAllDevices(renderView.hitTestMouseTrackers);
_mouseTracker!.updateAllDevices(renderView.hitTestMouseTrackers);
});
}
......@@ -455,29 +459,31 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
@override
void hitTest(HitTestResult result, Offset position) {
assert(renderView != null);
assert(result != null);
assert(position != null);
renderView.hitTest(result, position: position);
super.hitTest(result, position);
}
Future<void> _forceRepaint() {
RenderObjectVisitor visitor;
late RenderObjectVisitor visitor;
visitor = (RenderObject child) {
child.markNeedsPaint();
child.visitChildren(visitor);
};
instance?.renderView?.visitChildren(visitor);
instance?.renderView.visitChildren(visitor);
return endOfFrame;
}
}
/// Prints a textual representation of the entire render tree.
void debugDumpRenderTree() {
debugPrint(RendererBinding.instance?.renderView?.toStringDeep() ?? 'Render tree unavailable.');
debugPrint(RendererBinding.instance?.renderView.toStringDeep() ?? 'Render tree unavailable.');
}
/// Prints a textual representation of the entire layer tree.
void debugDumpLayerTree() {
debugPrint(RendererBinding.instance?.renderView?.debugLayer?.toStringDeep() ?? 'Layer tree unavailable.');
debugPrint(RendererBinding.instance?.renderView.debugLayer?.toStringDeep() ?? 'Layer tree unavailable.');
}
/// Prints a textual representation of the entire semantics tree.
......@@ -487,7 +493,7 @@ void debugDumpLayerTree() {
/// The order in which the children of a [SemanticsNode] will be printed is
/// controlled by the [childOrder] parameter.
void debugDumpSemanticsTree(DebugSemanticsDumpOrder childOrder) {
debugPrint(RendererBinding.instance?.renderView?.debugSemantics?.toStringDeep(childOrder: childOrder) ?? 'Semantics not collected.');
debugPrint(RendererBinding.instance?.renderView.debugSemantics?.toStringDeep(childOrder: childOrder) ?? 'Semantics not collected.');
}
/// A concrete binding for applications that use the Rendering framework
......@@ -502,7 +508,7 @@ class RenderingFlutterBinding extends BindingBase with GestureBinding, Scheduler
///
/// The `root` render box is attached directly to the [renderView] and is
/// given constraints that require it to fill the window.
RenderingFlutterBinding({ RenderBox root }) {
RenderingFlutterBinding({ RenderBox? root }) {
assert(renderView != null);
renderView.child = root;
}
......
This diff is collapsed.
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart';
import 'box.dart';
......@@ -14,7 +12,7 @@ import 'object.dart';
/// [ParentData] used by [RenderCustomMultiChildLayoutBox].
class MultiChildLayoutParentData extends ContainerBoxParentData<RenderBox> {
/// An object representing the identity of this child.
Object id;
Object? id;
@override
String toString() => '${super.toString()}; id=$id';
......@@ -120,20 +118,19 @@ abstract class MultiChildLayoutDelegate {
/// Creates a layout delegate.
///
/// The layout will update whenever [relayout] notifies its listeners.
MultiChildLayoutDelegate({ Listenable relayout }) : _relayout = relayout;
MultiChildLayoutDelegate({ Listenable? relayout }) : _relayout = relayout;
final Listenable _relayout;
final Listenable? _relayout;
// TODO(ianh): make these late final
/*late*/ Map<Object/*!*/, RenderBox>/*!*/ _idToChild;
/*late*/ Set<RenderBox/*!*/>/*!*/ _debugChildrenNeedingLayout;
Map<Object, RenderBox>? _idToChild;
Set<RenderBox>? _debugChildrenNeedingLayout;
/// True if a non-null LayoutChild was provided for the specified id.
///
/// Call this from the [performLayout] or [getSize] methods to
/// determine which children are available, if the child list might
/// vary.
bool hasChild(Object childId) => _idToChild[childId] != null;
bool hasChild(Object childId) => _idToChild![childId] != null;
/// Ask the child to update its layout within the limits specified by
/// the constraints parameter. The child's size is returned.
......@@ -141,8 +138,8 @@ abstract class MultiChildLayoutDelegate {
/// Call this from your [performLayout] function to lay out each
/// child. Every child must be laid out using this function exactly
/// once each time the [performLayout] function is called.
Size/*!*/ layoutChild(Object childId, BoxConstraints constraints) {
final RenderBox child = _idToChild[childId];
Size layoutChild(Object childId, BoxConstraints constraints) {
final RenderBox? child = _idToChild![childId];
assert(() {
if (child == null) {
throw FlutterError(
......@@ -150,7 +147,7 @@ abstract class MultiChildLayoutDelegate {
'There is no child with the id "$childId".'
);
}
if (!_debugChildrenNeedingLayout.remove(child)) {
if (!_debugChildrenNeedingLayout!.remove(child)) {
throw FlutterError(
'The $this custom multichild layout delegate tried to lay out the child with id "$childId" more than once.\n'
'Each child must be laid out exactly once.'
......@@ -171,7 +168,7 @@ abstract class MultiChildLayoutDelegate {
}
return true;
}());
child.layout(constraints, parentUsesSize: true);
child!.layout(constraints, parentUsesSize: true);
return child.size;
}
......@@ -182,7 +179,7 @@ abstract class MultiChildLayoutDelegate {
/// remain unchanged. Children initially have their position set to
/// (0,0), i.e. the top left of the [RenderCustomMultiChildLayoutBox].
void positionChild(Object childId, Offset offset) {
final RenderBox child = _idToChild[childId];
final RenderBox? child = _idToChild![childId];
assert(() {
if (child == null) {
throw FlutterError(
......@@ -190,14 +187,17 @@ abstract class MultiChildLayoutDelegate {
'There is no child with the id "$childId".'
);
}
if (offset == null) {
// `offset` has a non-nullable return type, but might be null when
// running with weak checking, so we need to null check it anyway (and
// ignore the warning that the null-handling logic is dead code).
if (offset == null) { // ignore: dead_code
throw FlutterError(
'The $this custom multichild layout delegate provided a null position for the child with id "$childId".'
);
}
return true;
}());
final MultiChildLayoutParentData childParentData = child.parentData as MultiChildLayoutParentData;
final MultiChildLayoutParentData childParentData = child!.parentData as MultiChildLayoutParentData;
childParentData.offset = offset;
}
......@@ -206,14 +206,13 @@ abstract class MultiChildLayoutDelegate {
return DiagnosticsProperty<RenderBox>('${childParentData.id}', child);
}
void _callPerformLayout(Size size, RenderBox firstChild) {
void _callPerformLayout(Size size, RenderBox? firstChild) {
// A particular layout delegate could be called reentrantly, e.g. if it used
// by both a parent and a child. So, we must restore the _idToChild map when
// we return.
final Map<Object, RenderBox> previousIdToChild = _idToChild;
final Map<Object, RenderBox>? previousIdToChild = _idToChild;
// TODO(ianh): make the next line final
/*late*/ Set<RenderBox>/*!*/ debugPreviousChildrenNeedingLayout;
Set<RenderBox>? debugPreviousChildrenNeedingLayout;
assert(() {
debugPreviousChildrenNeedingLayout = _debugChildrenNeedingLayout;
_debugChildrenNeedingLayout = <RenderBox>{};
......@@ -222,36 +221,36 @@ abstract class MultiChildLayoutDelegate {
try {
_idToChild = <Object, RenderBox>{};
RenderBox child = firstChild;
RenderBox? child = firstChild;
while (child != null) {
final MultiChildLayoutParentData childParentData = child.parentData as MultiChildLayoutParentData;
assert(() {
if (childParentData.id == null) {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('Every child of a RenderCustomMultiChildLayoutBox must have an ID in its parent data.'),
child.describeForError('The following child has no ID'),
child!.describeForError('The following child has no ID'),
]);
}
return true;
}());
_idToChild[childParentData.id] = child;
_idToChild![childParentData.id!] = child;
assert(() {
_debugChildrenNeedingLayout.add(child);
_debugChildrenNeedingLayout!.add(child!);
return true;
}());
child = childParentData.nextSibling;
}
performLayout(size);
assert(() {
if (_debugChildrenNeedingLayout.isNotEmpty) {
if (_debugChildrenNeedingLayout!.isNotEmpty) {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('Each child must be laid out exactly once.'),
DiagnosticsBlock(
name:
'The $this custom multichild layout delegate forgot '
'to lay out the following '
'${_debugChildrenNeedingLayout.length > 1 ? 'children' : 'child'}',
properties: _debugChildrenNeedingLayout.map<DiagnosticsNode>(_debugDescribeChild).toList(),
'${_debugChildrenNeedingLayout!.length > 1 ? 'children' : 'child'}',
properties: _debugChildrenNeedingLayout!.map<DiagnosticsNode>(_debugDescribeChild).toList(),
style: DiagnosticsTreeStyle.whitespace,
),
]);
......@@ -314,8 +313,8 @@ class RenderCustomMultiChildLayoutBox extends RenderBox
///
/// The [delegate] argument must not be null.
RenderCustomMultiChildLayoutBox({
List<RenderBox> children,
@required MultiChildLayoutDelegate delegate,
List<RenderBox>? children,
required MultiChildLayoutDelegate delegate,
}) : assert(delegate != null),
_delegate = delegate {
addAll(children);
......@@ -339,20 +338,20 @@ class RenderCustomMultiChildLayoutBox extends RenderBox
markNeedsLayout();
_delegate = newDelegate;
if (attached) {
oldDelegate?._relayout?.removeListener(markNeedsLayout);
newDelegate?._relayout?.addListener(markNeedsLayout);
oldDelegate._relayout?.removeListener(markNeedsLayout);
newDelegate._relayout?.addListener(markNeedsLayout);
}
}
@override
void attach(PipelineOwner owner) {
super.attach(owner);
_delegate?._relayout?.addListener(markNeedsLayout);
_delegate._relayout?.addListener(markNeedsLayout);
}
@override
void detach() {
_delegate?._relayout?.removeListener(markNeedsLayout);
_delegate._relayout?.removeListener(markNeedsLayout);
super.detach();
}
......@@ -409,7 +408,7 @@ class RenderCustomMultiChildLayoutBox extends RenderBox
}
@override
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
return defaultHitTestChildren(result, position: position);
}
}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart';
......@@ -88,6 +86,11 @@ bool debugRepaintTextRainbowEnabled = false;
///
/// This check helps developers that want a consistent look and feel detect
/// where this inconsistency would occur.
///
/// This check assumes that elevations on [PhysicalModelLayer] objects have
/// been set to non-null values before the scene is built. If this assumption
/// is violated, the check will throw exceptions. (The scene building would
/// also fail in that case, however.)
bool debugCheckElevationsEnabled = false;
/// The current color to overlay when repainting a layer.
......@@ -174,7 +177,7 @@ bool debugProfileLayoutsEnabled = false;
bool debugProfilePaintsEnabled = false;
/// Signature for [debugOnProfilePaint] implementations.
typedef ProfilePaintCallback = void Function(RenderObject/*!*/ renderObject);
typedef ProfilePaintCallback = void Function(RenderObject renderObject);
/// Callback invoked for every [RenderObject] painted each frame.
///
......@@ -190,7 +193,7 @@ typedef ProfilePaintCallback = void Function(RenderObject/*!*/ renderObject);
/// callback to generate aggregate profile statistics describing what paints
/// occurred when the `ext.flutter.inspector.trackRepaintWidgets` service
/// extension is enabled.
ProfilePaintCallback debugOnProfilePaint;
ProfilePaintCallback? debugOnProfilePaint;
/// Setting to true will cause all clipping effects from the layer tree to be
/// ignored.
......@@ -243,7 +246,7 @@ void _debugDrawDoubleRect(Canvas canvas, Rect outerRect, Rect innerRect, Color c
///
/// Called by [RenderPadding.debugPaintSize] when [debugPaintSizeEnabled] is
/// true.
void debugPaintPadding(Canvas canvas, Rect outerRect, Rect innerRect, { double outlineWidth = 2.0 }) {
void debugPaintPadding(Canvas canvas, Rect outerRect, Rect? innerRect, { double outlineWidth = 2.0 }) {
assert(() {
if (innerRect != null && !innerRect.isEmpty) {
_debugDrawDoubleRect(canvas, outerRect, innerRect, const Color(0x900090FF));
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math;
import 'dart:ui' as ui;
......@@ -25,11 +23,11 @@ enum _OverflowSide {
// the indicators.
class _OverflowRegionData {
const _OverflowRegionData({
this.rect,
required this.rect,
this.label = '',
this.labelOffset = Offset.zero,
this.rotation = 0.0,
this.side,
required this.side,
});
final Rect rect;
......@@ -201,7 +199,7 @@ mixin DebugOverflowIndicatorMixin on RenderObject {
return regions;
}
void _reportOverflow(RelativeRect overflow, List<DiagnosticsNode> overflowHints) {
void _reportOverflow(RelativeRect overflow, List<DiagnosticsNode>? overflowHints) {
overflowHints ??= <DiagnosticsNode>[];
if (overflowHints.isEmpty) {
overflowHints.add(ErrorDescription(
......@@ -248,8 +246,8 @@ mixin DebugOverflowIndicatorMixin on RenderObject {
context: ErrorDescription('during layout'),
informationCollector: () sync* {
if (debugCreator != null)
yield DiagnosticsDebugCreator(debugCreator);
yield* overflowHints;
yield DiagnosticsDebugCreator(debugCreator as Object);
yield* overflowHints!;
yield describeForError('The specific $runtimeType in question is');
// TODO(jacobr): this line is ascii art that it would be nice to
// handle a little more generically in GUI debugging clients in the
......@@ -271,7 +269,7 @@ mixin DebugOverflowIndicatorMixin on RenderObject {
Offset offset,
Rect containerRect,
Rect childRect, {
List<DiagnosticsNode> overflowHints,
List<DiagnosticsNode>? overflowHints,
}) {
final RelativeRect overflow = RelativeRect.fromRect(containerRect, childRect);
......@@ -285,7 +283,7 @@ mixin DebugOverflowIndicatorMixin on RenderObject {
final List<_OverflowRegionData> overflowRegions = _calculateOverflowRegions(overflow, containerRect);
for (final _OverflowRegionData region in overflowRegions) {
context.canvas.drawRect(region.rect.shift(offset), _indicatorPaint);
final TextSpan textSpan = _indicatorLabel[region.side.index].text as TextSpan;
final TextSpan? textSpan = _indicatorLabel[region.side.index].text as TextSpan?;
if (textSpan?.text != region.label) {
_indicatorLabel[region.side.index].text = TextSpan(
text: region.label,
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' as ui show Paragraph, ParagraphBuilder, ParagraphConstraints, ParagraphStyle, TextStyle;
import 'box.dart';
......@@ -59,7 +57,7 @@ class RenderErrorBox extends RenderBox {
final String message;
// TODO(ianh): should be final
/*late*/ ui.Paragraph/*?*/ _paragraph;
ui.Paragraph? _paragraph;
@override
double computeMaxIntrinsicWidth(double height) {
......@@ -158,11 +156,11 @@ class RenderErrorBox extends RenderBox {
width -= padding.left + padding.right;
left += padding.left;
}
_paragraph.layout(ui.ParagraphConstraints(width: width));
if (size.height > padding.top + _paragraph.height + padding.bottom) {
_paragraph!.layout(ui.ParagraphConstraints(width: width));
if (size.height > padding.top + _paragraph!.height + padding.bottom) {
top += padding.top;
}
context.canvas.drawParagraph(_paragraph, offset + Offset(left, top));
context.canvas.drawParagraph(_paragraph!, offset + Offset(left, top));
}
} catch (e) {
// Intentionally left empty.
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' as ui show Color;
import 'package:flutter/foundation.dart';
......@@ -32,7 +30,7 @@ abstract class FlowPaintingContext {
/// The size of the [i]th child.
///
/// If [i] is negative or exceeds [childCount], returns null.
Size getChildSize(int i);
Size? getChildSize(int i);
/// Paint the [i]th child using the given transform.
///
......@@ -59,9 +57,9 @@ abstract class FlowPaintingContext {
/// * [RenderFlow]
abstract class FlowDelegate {
/// The flow will repaint whenever [repaint] notifies its listeners.
const FlowDelegate({ Listenable repaint }) : _repaint = repaint;
const FlowDelegate({ Listenable? repaint }) : _repaint = repaint;
final Listenable _repaint;
final Listenable? _repaint;
/// Override to control the size of the container for the children.
///
......@@ -145,7 +143,7 @@ abstract class FlowDelegate {
/// matrix, use the [FlowPaintingContext.paintChild] function from an override
/// of the [FlowDelegate.paintChildren] function.
class FlowParentData extends ContainerBoxParentData<RenderBox> {
Matrix4 _transform;
Matrix4? _transform;
}
/// Implements the flow layout algorithm.
......@@ -181,8 +179,8 @@ class RenderFlow extends RenderBox
/// For optimal performance, consider using children that return true from
/// [isRepaintBoundary].
RenderFlow({
List<RenderBox> children,
@required FlowDelegate delegate,
List<RenderBox>? children,
required FlowDelegate delegate,
}) : assert(delegate != null),
_delegate = delegate {
addAll(children);
......@@ -190,7 +188,7 @@ class RenderFlow extends RenderBox
@override
void setupParentData(RenderBox child) {
final ParentData childParentData = child.parentData;
final ParentData? childParentData = child.parentData;
if (childParentData is FlowParentData)
childParentData._transform = null;
else
......@@ -285,7 +283,7 @@ class RenderFlow extends RenderBox
size = _getSize(constraints);
int i = 0;
_randomAccessChildren.clear();
RenderBox child = firstChild;
RenderBox? child = firstChild;
while (child != null) {
_randomAccessChildren.add(child);
final BoxConstraints innerConstraints = _delegate.getConstraintsForChild(i, constraints);
......@@ -304,18 +302,18 @@ class RenderFlow extends RenderBox
final List<int> _lastPaintOrder = <int>[];
// Only valid during paint.
PaintingContext _paintingContext;
Offset _paintingOffset;
PaintingContext? _paintingContext;
Offset? _paintingOffset;
@override
Size getChildSize(int i) {
Size? getChildSize(int i) {
if (i < 0 || i >= _randomAccessChildren.length)
return null;
return _randomAccessChildren[i].size;
}
@override
void paintChild(int i, { Matrix4 transform, double opacity = 1.0 }) {
void paintChild(int i, { Matrix4? transform, double opacity = 1.0 }) {
transform ??= Matrix4.identity();
final RenderBox child = _randomAccessChildren[i];
final FlowParentData childParentData = child.parentData as FlowParentData;
......@@ -341,10 +339,10 @@ class RenderFlow extends RenderBox
context.paintChild(child, offset);
}
if (opacity == 1.0) {
_paintingContext.pushTransform(needsCompositing, _paintingOffset, transform, painter);
_paintingContext!.pushTransform(needsCompositing, _paintingOffset!, transform, painter);
} else {
_paintingContext.pushOpacity(_paintingOffset, ui.Color.getAlphaFromOpacity(opacity), (PaintingContext context, Offset offset) {
context.pushTransform(needsCompositing, offset, transform, painter);
_paintingContext!.pushOpacity(_paintingOffset!, ui.Color.getAlphaFromOpacity(opacity), (PaintingContext context, Offset offset) {
context.pushTransform(needsCompositing, offset, transform!, painter);
});
}
}
......@@ -371,7 +369,7 @@ class RenderFlow extends RenderBox
}
@override
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
final List<RenderBox> children = getChildrenAsList();
for (int i = _lastPaintOrder.length - 1; i >= 0; --i) {
final int childIndex = _lastPaintOrder[i];
......@@ -379,14 +377,14 @@ class RenderFlow extends RenderBox
continue;
final RenderBox child = children[childIndex];
final FlowParentData childParentData = child.parentData as FlowParentData;
final Matrix4 transform = childParentData._transform;
final Matrix4? transform = childParentData._transform;
if (transform == null)
continue;
final bool absorbed = result.addWithPaintTransform(
transform: transform,
position: position,
hitTest: (BoxHitTestResult result, Offset position) {
return child.hitTest(result, position: position);
hitTest: (BoxHitTestResult result, Offset? position) {
return child.hitTest(result, position: position!);
},
);
if (absorbed)
......@@ -399,7 +397,7 @@ class RenderFlow extends RenderBox
void applyPaintTransform(RenderBox child, Matrix4 transform) {
final FlowParentData childParentData = child.parentData as FlowParentData;
if (childParentData._transform != null)
transform.multiply(childParentData._transform);
transform.multiply(childParentData._transform!);
super.applyPaintTransform(child, transform);
}
}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' as ui show Image;
import 'box.dart';
......@@ -27,19 +25,19 @@ class RenderImage extends RenderBox {
/// must not be null. The [textDirection] argument must not be null if
/// [alignment] will need resolving or if [matchTextDirection] is true.
RenderImage({
ui.Image image,
ui.Image? image,
this.debugImageLabel,
double width,
double height,
double? width,
double? height,
double scale = 1.0,
Color color,
BlendMode colorBlendMode,
BoxFit fit,
Color? color,
BlendMode? colorBlendMode,
BoxFit? fit,
AlignmentGeometry alignment = Alignment.center,
ImageRepeat repeat = ImageRepeat.noRepeat,
Rect centerSlice,
Rect? centerSlice,
bool matchTextDirection = false,
TextDirection textDirection,
TextDirection? textDirection,
bool invertColors = false,
bool isAntiAlias = false,
FilterQuality filterQuality = FilterQuality.low,
......@@ -67,8 +65,8 @@ class RenderImage extends RenderBox {
_updateColorFilter();
}
Alignment _resolvedAlignment;
bool _flipHorizontally;
Alignment? _resolvedAlignment;
bool? _flipHorizontally;
void _resolve() {
if (_resolvedAlignment != null)
......@@ -84,9 +82,9 @@ class RenderImage extends RenderBox {
}
/// The image to display.
ui.Image get image => _image;
ui.Image _image;
set image(ui.Image value) {
ui.Image? get image => _image;
ui.Image? _image;
set image(ui.Image? value) {
if (value == _image)
return;
_image = value;
......@@ -96,15 +94,15 @@ class RenderImage extends RenderBox {
}
/// A string used to identify the source of the image.
String debugImageLabel;
String? debugImageLabel;
/// If non-null, requires the image to have this width.
///
/// If null, the image will pick a size that best preserves its intrinsic
/// aspect ratio.
double get width => _width;
double _width;
set width(double value) {
double? get width => _width;
double? _width;
set width(double? value) {
if (value == _width)
return;
_width = value;
......@@ -115,9 +113,9 @@ class RenderImage extends RenderBox {
///
/// If null, the image will pick a size that best preserves its intrinsic
/// aspect ratio.
double get height => _height;
double _height;
set height(double value) {
double? get height => _height;
double? _height;
set height(double? value) {
if (value == _height)
return;
_height = value;
......@@ -137,19 +135,19 @@ class RenderImage extends RenderBox {
markNeedsLayout();
}
ColorFilter _colorFilter;
ColorFilter? _colorFilter;
void _updateColorFilter() {
if (_color == null)
_colorFilter = null;
else
_colorFilter = ColorFilter.mode(_color, _colorBlendMode ?? BlendMode.srcIn);
_colorFilter = ColorFilter.mode(_color!, _colorBlendMode ?? BlendMode.srcIn);
}
/// If non-null, this color is blended with each image pixel using [colorBlendMode].
Color get color => _color;
Color _color;
set color(Color value) {
Color? get color => _color;
Color? _color;
set color(Color? value) {
if (value == _color)
return;
_color = value;
......@@ -180,9 +178,9 @@ class RenderImage extends RenderBox {
/// See also:
///
/// * [BlendMode], which includes an illustration of the effect of each blend mode.
BlendMode get colorBlendMode => _colorBlendMode;
BlendMode _colorBlendMode;
set colorBlendMode(BlendMode value) {
BlendMode? get colorBlendMode => _colorBlendMode;
BlendMode? _colorBlendMode;
set colorBlendMode(BlendMode? value) {
if (value == _colorBlendMode)
return;
_colorBlendMode = value;
......@@ -194,9 +192,9 @@ class RenderImage extends RenderBox {
///
/// The default varies based on the other fields. See the discussion at
/// [paintImage].
BoxFit get fit => _fit;
BoxFit _fit;
set fit(BoxFit value) {
BoxFit? get fit => _fit;
BoxFit? _fit;
set fit(BoxFit? value) {
if (value == _fit)
return;
_fit = value;
......@@ -235,9 +233,9 @@ class RenderImage extends RenderBox {
/// region of the image above and below the center slice will be stretched
/// only horizontally and the region of the image to the left and right of
/// the center slice will be stretched only vertically.
Rect get centerSlice => _centerSlice;
Rect _centerSlice;
set centerSlice(Rect value) {
Rect? get centerSlice => _centerSlice;
Rect? _centerSlice;
set centerSlice(Rect? value) {
if (value == _centerSlice)
return;
_centerSlice = value;
......@@ -287,9 +285,9 @@ class RenderImage extends RenderBox {
/// This may be changed to null, but only after the [alignment] and
/// [matchTextDirection] properties have been changed to values that do not
/// depend on the direction.
TextDirection get textDirection => _textDirection;
TextDirection _textDirection;
set textDirection(TextDirection value) {
TextDirection? get textDirection => _textDirection;
TextDirection? _textDirection;
set textDirection(TextDirection? value) {
if (_textDirection == value)
return;
_textDirection = value;
......@@ -329,8 +327,8 @@ class RenderImage extends RenderBox {
return constraints.smallest;
return constraints.constrainSizeAndAttemptToPreserveAspectRatio(Size(
_image.width.toDouble() / _scale,
_image.height.toDouble() / _scale,
_image!.width.toDouble() / _scale,
_image!.height.toDouble() / _scale,
));
}
......@@ -380,15 +378,15 @@ class RenderImage extends RenderBox {
paintImage(
canvas: context.canvas,
rect: offset & size,
image: _image,
image: _image!,
debugImageLabel: debugImageLabel,
scale: _scale,
colorFilter: _colorFilter,
fit: _fit,
alignment: _resolvedAlignment,
alignment: _resolvedAlignment!,
centerSlice: _centerSlice,
repeat: _repeat,
flipHorizontally: _flipHorizontally,
flipHorizontally: _flipHorizontally!,
invertColors: invertColors,
filterQuality: _filterQuality,
isAntiAlias: _isAntiAlias,
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math;
import 'box.dart';
......@@ -32,7 +30,7 @@ class RenderListBody extends RenderBox
///
/// By default, children are arranged along the vertical axis.
RenderListBody({
List<RenderBox> children,
List<RenderBox>? children,
AxisDirection axisDirection = AxisDirection.down,
}) : assert(axisDirection != null),
_axisDirection = axisDirection {
......@@ -123,7 +121,7 @@ class RenderListBody extends RenderBox
]);
}());
double mainAxisExtent = 0.0;
RenderBox child = firstChild;
RenderBox? child = firstChild;
switch (axisDirection) {
case AxisDirection.right:
final BoxConstraints innerConstraints = BoxConstraints.tightFor(height: constraints.maxHeight);
......@@ -201,7 +199,7 @@ class RenderListBody extends RenderBox
double _getIntrinsicCrossAxis(_ChildSizingFunction childSize) {
double extent = 0.0;
RenderBox child = firstChild;
RenderBox? child = firstChild;
while (child != null) {
extent = math.max(extent, childSize(child));
final ListBodyParentData childParentData = child.parentData as ListBodyParentData;
......@@ -212,7 +210,7 @@ class RenderListBody extends RenderBox
double _getIntrinsicMainAxis(_ChildSizingFunction childSize) {
double extent = 0.0;
RenderBox child = firstChild;
RenderBox? child = firstChild;
while (child != null) {
extent += childSize(child);
final ListBodyParentData childParentData = child.parentData as ListBodyParentData;
......@@ -230,7 +228,6 @@ class RenderListBody extends RenderBox
case Axis.vertical:
return _getIntrinsicCrossAxis((RenderBox child) => child.getMinIntrinsicWidth(height));
}
return null;
}
@override
......@@ -242,7 +239,6 @@ class RenderListBody extends RenderBox
case Axis.vertical:
return _getIntrinsicCrossAxis((RenderBox child) => child.getMaxIntrinsicWidth(height));
}
return null;
}
@override
......@@ -254,7 +250,6 @@ class RenderListBody extends RenderBox
case Axis.vertical:
return _getIntrinsicCrossAxis((RenderBox child) => child.getMinIntrinsicHeight(width));
}
return null;
}
@override
......@@ -266,11 +261,10 @@ class RenderListBody extends RenderBox
case Axis.vertical:
return _getIntrinsicCrossAxis((RenderBox child) => child.getMaxIntrinsicHeight(width));
}
return null;
}
@override
double computeDistanceToActualBaseline(TextBaseline baseline) {
double? computeDistanceToActualBaseline(TextBaseline baseline) {
return defaultComputeDistanceToFirstActualBaseline(baseline);
}
......@@ -280,7 +274,7 @@ class RenderListBody extends RenderBox
}
@override
bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
return defaultHitTestChildren(result, position: position);
}
......
......@@ -2,12 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math;
import 'package:flutter/animation.dart';
import 'package:flutter/foundation.dart';
import 'package:vector_math/vector_math_64.dart' show Matrix4;
import 'box.dart';
......@@ -30,7 +27,7 @@ abstract class ListWheelChildManager {
/// If null, then there's no explicit limits to the range of the children
/// except that it has to be contiguous. If [childExistsAt] for a certain
/// index returns false, that index is already past the limit.
int get childCount;
int? get childCount;
/// Checks whether the delegate is able to provide a child widget at the given
/// index.
......@@ -44,7 +41,7 @@ abstract class ListWheelChildManager {
/// nothing.
///
/// It is possible to create children with negative indices.
void createChild(int index, { @required RenderBox after });
void createChild(int index, { required RenderBox? after });
/// Removes the child element corresponding with the given RenderBox.
void removeChild(RenderBox child);
......@@ -53,7 +50,9 @@ abstract class ListWheelChildManager {
/// [ParentData] for use with [RenderListWheelViewport].
class ListWheelParentData extends ContainerBoxParentData<RenderBox> {
/// Index of this child in its parent's child list.
int index;
///
/// This must be maintained by the [ListWheelChildManager].
int? index;
}
/// Render, onto a wheel, a bigger sequential set of objects inside this viewport.
......@@ -135,19 +134,19 @@ class RenderListWheelViewport
///
/// All arguments must not be null. Optional arguments have reasonable defaults.
RenderListWheelViewport({
@required this.childManager,
@required ViewportOffset offset,
required this.childManager,
required ViewportOffset offset,
double diameterRatio = defaultDiameterRatio,
double perspective = defaultPerspective,
double offAxisFraction = 0,
bool useMagnifier = false,
double magnification = 1,
double overAndUnderCenterOpacity = 1,
@required double itemExtent,
required double itemExtent,
double squeeze = 1,
bool renderChildrenOutsideViewport = false,
Clip clipBehavior = Clip.none,
List<RenderBox> children,
List<RenderBox>? children,
}) : assert(childManager != null),
assert(offset != null),
assert(diameterRatio != null),
......@@ -208,6 +207,8 @@ class RenderListWheelViewport
'rendered outside will be clipped anyway.';
/// The delegate that manages the children of this object.
///
/// This delegate must maintain the [ListWheelParentData.index] value.
final ListWheelChildManager childManager;
/// The associated ViewportOffset object for the viewport describing the part
......@@ -530,7 +531,7 @@ class RenderListWheelViewport
if (childManager.childCount == null)
return double.infinity;
return math.max(0.0, (childManager.childCount - 1) * _itemExtent);
return math.max(0.0, (childManager.childCount! - 1) * _itemExtent);
}
/// Scroll extent distance in the untransformed plane between the center
......@@ -567,7 +568,7 @@ class RenderListWheelViewport
double _getIntrinsicCrossAxis(_ChildSizingFunction childSize) {
double extent = 0.0;
RenderBox child = firstChild;
RenderBox? child = firstChild;
while (child != null) {
extent = math.max(extent, childSize(child));
child = childAfter(child);
......@@ -593,14 +594,14 @@ class RenderListWheelViewport
double computeMinIntrinsicHeight(double width) {
if (childManager.childCount == null)
return 0.0;
return childManager.childCount * _itemExtent;
return childManager.childCount! * _itemExtent;
}
@override
double computeMaxIntrinsicHeight(double width) {
if (childManager.childCount == null)
return 0.0;
return childManager.childCount * _itemExtent;
return childManager.childCount! * _itemExtent;
}
@override
......@@ -611,12 +612,14 @@ class RenderListWheelViewport
size = constraints.biggest;
}
/// Gets the index of a child by looking at its parentData.
/// Gets the index of a child by looking at its [parentData].
///
/// This relies on the [childManager] maintaining [ListWheelParentData.index].
int indexOf(RenderBox child) {
assert(child != null);
final ListWheelParentData childParentData = child.parentData as ListWheelParentData;
assert(childParentData.index != null);
return childParentData.index;
return childParentData.index!;
}
/// Returns the index of the child at the given offset.
......@@ -625,7 +628,7 @@ class RenderListWheelViewport
/// Returns the scroll offset of the child with the given index.
double indexToScrollOffset(int index) => index * itemExtent;
void _createChild(int index, { RenderBox after }) {
void _createChild(int index, { RenderBox? after }) {
invokeLayoutCallback<BoxConstraints>((BoxConstraints constraints) {
assert(constraints == this.constraints);
childManager.createChild(index, after: after);
......@@ -697,7 +700,7 @@ class RenderListWheelViewport
// return.
if (targetFirstIndex > targetLastIndex) {
while (firstChild != null)
_destroyChild(firstChild);
_destroyChild(firstChild!);
return;
}
......@@ -711,34 +714,34 @@ class RenderListWheelViewport
// Case when there is no intersection.
if (childCount > 0 &&
(indexOf(firstChild) > targetLastIndex || indexOf(lastChild) < targetFirstIndex)) {
(indexOf(firstChild!) > targetLastIndex || indexOf(lastChild!) < targetFirstIndex)) {
while (firstChild != null)
_destroyChild(firstChild);
_destroyChild(firstChild!);
}
// If there is no child at this stage, we add the first one that is in
// target range.
if (childCount == 0) {
_createChild(targetFirstIndex);
_layoutChild(firstChild, childConstraints, targetFirstIndex);
_layoutChild(firstChild!, childConstraints, targetFirstIndex);
}
int currentFirstIndex = indexOf(firstChild);
int currentLastIndex = indexOf(lastChild);
int currentFirstIndex = indexOf(firstChild!);
int currentLastIndex = indexOf(lastChild!);
// Remove all unnecessary children by shortening the current child list, in
// both directions.
while (currentFirstIndex < targetFirstIndex) {
_destroyChild(firstChild);
_destroyChild(firstChild!);
currentFirstIndex++;
}
while (currentLastIndex > targetLastIndex) {
_destroyChild(lastChild);
_destroyChild(lastChild!);
currentLastIndex--;
}
// Relayout all active children.
RenderBox child = firstChild;
RenderBox? child = firstChild;
while (child != null) {
child.layout(childConstraints, parentUsesSize: true);
child = childAfter(child);
......@@ -747,11 +750,11 @@ class RenderListWheelViewport
// Spawning new children that are actually visible but not in child list yet.
while (currentFirstIndex > targetFirstIndex) {
_createChild(currentFirstIndex - 1);
_layoutChild(firstChild, childConstraints, --currentFirstIndex);
_layoutChild(firstChild!, childConstraints, --currentFirstIndex);
}
while (currentLastIndex < targetLastIndex) {
_createChild(currentLastIndex + 1, after: lastChild);
_layoutChild(lastChild, childConstraints, ++currentLastIndex);
_layoutChild(lastChild!, childConstraints, ++currentLastIndex);
}
offset.applyViewportDimension(_viewportExtent);
......@@ -796,13 +799,11 @@ class RenderListWheelViewport
/// Paints all children visible in the current viewport.
void _paintVisibleChildren(PaintingContext context, Offset offset) {
RenderBox childToPaint = firstChild;
ListWheelParentData childParentData = childToPaint?.parentData as ListWheelParentData;
while (childParentData != null) {
RenderBox? childToPaint = firstChild;
while (childToPaint != null) {
final ListWheelParentData childParentData = childToPaint.parentData! as ListWheelParentData;
_paintTransformedChild(childToPaint, context, offset, childParentData.offset);
childToPaint = childAfter(childToPaint);
childParentData = childToPaint?.parentData as ListWheelParentData;
}
}
......@@ -988,23 +989,23 @@ class RenderListWheelViewport
/// painting coordinates** system.
@override
void applyPaintTransform(RenderBox child, Matrix4 transform) {
final ListWheelParentData parentData = child?.parentData as ListWheelParentData;
final ListWheelParentData parentData = child.parentData as ListWheelParentData;
transform.translate(0.0, _getUntransformedPaintingCoordinateY(parentData.offset.dy));
}
@override
Rect describeApproximatePaintClip(RenderObject child) {
if (child != null && _shouldClipAtCurrentOffset()) {
Rect? describeApproximatePaintClip(RenderObject child) {
if (_shouldClipAtCurrentOffset()) {
return Offset.zero & size;
}
return null;
}
@override
bool hitTestChildren(BoxHitTestResult result, { Offset position }) => false;
bool hitTestChildren(BoxHitTestResult result, { required Offset position }) => false;
@override
RevealedOffset getOffsetToReveal(RenderObject target, double alignment, { Rect rect }) {
RevealedOffset getOffsetToReveal(RenderObject target, double alignment, { Rect? rect }) {
// `target` is only fully revealed when in the selected/center position. Therefore,
// this method always returns the offset that shows `target` in the center position,
// which is the same offset for all `alignment` values.
......@@ -1028,8 +1029,8 @@ class RenderListWheelViewport
@override
void showOnScreen({
RenderObject descendant,
Rect rect,
RenderObject? descendant,
Rect? rect,
Duration duration = Duration.zero,
Curve curve = Curves.ease,
}) {
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'box.dart';
import 'layer.dart';
import 'object.dart';
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import '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);
......
......@@ -216,8 +216,8 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
/// To use a different [RestorationManager] subclasses can override
/// [createRestorationManager], which is called to create the instance
/// returned by this getter.
RestorationManager get restorationManager => _restorationManager!;
RestorationManager? _restorationManager;
RestorationManager get restorationManager => _restorationManager;
late RestorationManager _restorationManager;
/// Creates the [RestorationManager] instance available via
/// [restorationManager].
......
......@@ -2677,8 +2677,12 @@ class BuildOwner {
e,
stack,
informationCollector: () sync* {
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.');
}
},
);
}
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment