• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'dart:math' as math;
6import 'dart:ui' as ui show lerpDouble;
7
8import 'package:flutter/foundation.dart';
9import 'package:flutter/gestures.dart';
10
11import 'package:vector_math/vector_math_64.dart';
12
13import 'debug.dart';
14import 'object.dart';
15
16// This class should only be used in debug builds.
17class _DebugSize extends Size {
18  _DebugSize(Size source, this._owner, this._canBeUsedByParent) : super.copy(source);
19  final RenderBox _owner;
20  final bool _canBeUsedByParent;
21}
22
23/// Immutable layout constraints for [RenderBox] layout.
24///
25/// A [Size] respects a [BoxConstraints] if, and only if, all of the following
26/// relations hold:
27///
28/// * [minWidth] <= [Size.width] <= [maxWidth]
29/// * [minHeight] <= [Size.height] <= [maxHeight]
30///
31/// The constraints themselves must satisfy these relations:
32///
33/// * 0.0 <= [minWidth] <= [maxWidth] <= [double.infinity]
34/// * 0.0 <= [minHeight] <= [maxHeight] <= [double.infinity]
35///
36/// [double.infinity] is a legal value for each constraint.
37///
38/// ## The box layout model
39///
40/// Render objects in the Flutter framework are laid out by a one-pass layout
41/// model which walks down the render tree passing constraints, then walks back
42/// up the render tree passing concrete geometry.
43///
44/// For boxes, the constraints are [BoxConstraints], which, as described herein,
45/// consist of four numbers: a minimum width [minWidth], a maximum width
46/// [maxWidth], a minimum height [minHeight], and a maximum height [maxHeight].
47///
48/// The geometry for boxes consists of a [Size], which must satisfy the
49/// constraints described above.
50///
51/// Each [RenderBox] (the objects that provide the layout models for box
52/// widgets) receives [BoxConstraints] from its parent, then lays out each of
53/// its children, then picks a [Size] that satisfies the [BoxConstraints].
54///
55/// Render objects position their children independently of laying them out.
56/// Frequently, the parent will use the children's sizes to determine their
57/// position. A child does not know its position and will not necessarily be
58/// laid out again, or repainted, if its position changes.
59///
60/// ## Terminology
61///
62/// When the minimum constraints and the maximum constraint in an axis are the
63/// same, that axis is _tightly_ constrained. See: [new
64/// BoxConstraints.tightFor], [new BoxConstraints.tightForFinite], [tighten],
65/// [hasTightWidth], [hasTightHeight], [isTight].
66///
67/// An axis with a minimum constraint of 0.0 is _loose_ (regardless of the
68/// maximum constraint; if it is also 0.0, then the axis is simultaneously tight
69/// and loose!). See: [new BoxConstraints.loose], [loosen].
70///
71/// An axis whose maximum constraint is not infinite is _bounded_. See:
72/// [hasBoundedWidth], [hasBoundedHeight].
73///
74/// An axis whose maximum constraint is infinite is _unbounded_. An axis is
75/// _expanding_ if it is tightly infinite (its minimum and maximum constraints
76/// are both infinite). See: [new BoxConstraints.expand].
77///
78/// An axis whose _minimum_ constraint is infinite is just said to be _infinite_
79/// (since by definition the maximum constraint must also be infinite in that
80/// case). See: [hasInfiniteWidth], [hasInfiniteHeight].
81///
82/// A size is _constrained_ when it satisfies a [BoxConstraints] description.
83/// See: [constrain], [constrainWidth], [constrainHeight],
84/// [constrainDimensions], [constrainSizeAndAttemptToPreserveAspectRatio],
85/// [isSatisfiedBy].
86class BoxConstraints extends Constraints {
87  /// Creates box constraints with the given constraints.
88  const BoxConstraints({
89    this.minWidth = 0.0,
90    this.maxWidth = double.infinity,
91    this.minHeight = 0.0,
92    this.maxHeight = double.infinity,
93  });
94
95  /// Creates box constraints that is respected only by the given size.
96  BoxConstraints.tight(Size size)
97    : minWidth = size.width,
98      maxWidth = size.width,
99      minHeight = size.height,
100      maxHeight = size.height;
101
102  /// Creates box constraints that require the given width or height.
103  ///
104  /// See also:
105  ///
106  ///  * [new BoxConstraints.tightForFinite], which is similar but instead of
107  ///    being tight if the value is non-null, is tight if the value is not
108  ///    infinite.
109  const BoxConstraints.tightFor({
110    double width,
111    double height,
112  }) : minWidth = width ?? 0.0,
113       maxWidth = width ?? double.infinity,
114       minHeight = height ?? 0.0,
115       maxHeight = height ?? double.infinity;
116
117  /// Creates box constraints that require the given width or height, except if
118  /// they are infinite.
119  ///
120  /// See also:
121  ///
122  ///  * [new BoxConstraints.tightFor], which is similar but instead of being
123  ///    tight if the value is not infinite, is tight if the value is non-null.
124  const BoxConstraints.tightForFinite({
125    double width = double.infinity,
126    double height = double.infinity,
127  }) : minWidth = width != double.infinity ? width : 0.0,
128       maxWidth = width != double.infinity ? width : double.infinity,
129       minHeight = height != double.infinity ? height : 0.0,
130       maxHeight = height != double.infinity ? height : double.infinity;
131
132  /// Creates box constraints that forbid sizes larger than the given size.
133  BoxConstraints.loose(Size size)
134    : minWidth = 0.0,
135      maxWidth = size.width,
136      minHeight = 0.0,
137      maxHeight = size.height;
138
139  /// Creates box constraints that expand to fill another box constraints.
140  ///
141  /// If width or height is given, the constraints will require exactly the
142  /// given value in the given dimension.
143  const BoxConstraints.expand({
144    double width,
145    double height,
146  }) : minWidth = width ?? double.infinity,
147       maxWidth = width ?? double.infinity,
148       minHeight = height ?? double.infinity,
149       maxHeight = height ?? double.infinity;
150
151  /// The minimum width that satisfies the constraints.
152  final double minWidth;
153
154  /// The maximum width that satisfies the constraints.
155  ///
156  /// Might be [double.infinity].
157  final double maxWidth;
158
159  /// The minimum height that satisfies the constraints.
160  final double minHeight;
161
162  /// The maximum height that satisfies the constraints.
163  ///
164  /// Might be [double.infinity].
165  final double maxHeight;
166
167  /// Creates a copy of this box constraints but with the given fields replaced with the new values.
168  BoxConstraints copyWith({
169    double minWidth,
170    double maxWidth,
171    double minHeight,
172    double maxHeight,
173  }) {
174    return BoxConstraints(
175      minWidth: minWidth ?? this.minWidth,
176      maxWidth: maxWidth ?? this.maxWidth,
177      minHeight: minHeight ?? this.minHeight,
178      maxHeight: maxHeight ?? this.maxHeight,
179    );
180  }
181
182  /// Returns new box constraints that are smaller by the given edge dimensions.
183  BoxConstraints deflate(EdgeInsets edges) {
184    assert(edges != null);
185    assert(debugAssertIsValid());
186    final double horizontal = edges.horizontal;
187    final double vertical = edges.vertical;
188    final double deflatedMinWidth = math.max(0.0, minWidth - horizontal);
189    final double deflatedMinHeight = math.max(0.0, minHeight - vertical);
190    return BoxConstraints(
191      minWidth: deflatedMinWidth,
192      maxWidth: math.max(deflatedMinWidth, maxWidth - horizontal),
193      minHeight: deflatedMinHeight,
194      maxHeight: math.max(deflatedMinHeight, maxHeight - vertical),
195    );
196  }
197
198  /// Returns new box constraints that remove the minimum width and height requirements.
199  BoxConstraints loosen() {
200    assert(debugAssertIsValid());
201    return BoxConstraints(
202      minWidth: 0.0,
203      maxWidth: maxWidth,
204      minHeight: 0.0,
205      maxHeight: maxHeight,
206    );
207  }
208
209  /// Returns new box constraints that respect the given constraints while being
210  /// as close as possible to the original constraints.
211  BoxConstraints enforce(BoxConstraints constraints) {
212    return BoxConstraints(
213      minWidth: minWidth.clamp(constraints.minWidth, constraints.maxWidth),
214      maxWidth: maxWidth.clamp(constraints.minWidth, constraints.maxWidth),
215      minHeight: minHeight.clamp(constraints.minHeight, constraints.maxHeight),
216      maxHeight: maxHeight.clamp(constraints.minHeight, constraints.maxHeight),
217    );
218  }
219
220  /// Returns new box constraints with a tight width and/or height as close to
221  /// the given width and height as possible while still respecting the original
222  /// box constraints.
223  BoxConstraints tighten({ double width, double height }) {
224    return BoxConstraints(minWidth: width == null ? minWidth : width.clamp(minWidth, maxWidth),
225                              maxWidth: width == null ? maxWidth : width.clamp(minWidth, maxWidth),
226                              minHeight: height == null ? minHeight : height.clamp(minHeight, maxHeight),
227                              maxHeight: height == null ? maxHeight : height.clamp(minHeight, maxHeight));
228  }
229
230  /// A box constraints with the width and height constraints flipped.
231  BoxConstraints get flipped {
232    return BoxConstraints(
233      minWidth: minHeight,
234      maxWidth: maxHeight,
235      minHeight: minWidth,
236      maxHeight: maxWidth,
237    );
238  }
239
240  /// Returns box constraints with the same width constraints but with
241  /// unconstrained height.
242  BoxConstraints widthConstraints() => BoxConstraints(minWidth: minWidth, maxWidth: maxWidth);
243
244  /// Returns box constraints with the same height constraints but with
245  /// unconstrained width
246  BoxConstraints heightConstraints() => BoxConstraints(minHeight: minHeight, maxHeight: maxHeight);
247
248  /// Returns the width that both satisfies the constraints and is as close as
249  /// possible to the given width.
250  double constrainWidth([ double width = double.infinity ]) {
251    assert(debugAssertIsValid());
252    return width.clamp(minWidth, maxWidth);
253  }
254
255  /// Returns the height that both satisfies the constraints and is as close as
256  /// possible to the given height.
257  double constrainHeight([ double height = double.infinity ]) {
258    assert(debugAssertIsValid());
259    return height.clamp(minHeight, maxHeight);
260  }
261
262  Size _debugPropagateDebugSize(Size size, Size result) {
263    assert(() {
264      if (size is _DebugSize)
265        result = _DebugSize(result, size._owner, size._canBeUsedByParent);
266      return true;
267    }());
268    return result;
269  }
270
271  /// Returns the size that both satisfies the constraints and is as close as
272  /// possible to the given size.
273  ///
274  /// See also [constrainDimensions], which applies the same algorithm to
275  /// separately provided widths and heights.
276  Size constrain(Size size) {
277    Size result = Size(constrainWidth(size.width), constrainHeight(size.height));
278    assert(() { result = _debugPropagateDebugSize(size, result); return true; }());
279    return result;
280  }
281
282  /// Returns the size that both satisfies the constraints and is as close as
283  /// possible to the given width and height.
284  ///
285  /// When you already have a [Size], prefer [constrain], which applies the same
286  /// algorithm to a [Size] directly.
287  Size constrainDimensions(double width, double height) {
288    return Size(constrainWidth(width), constrainHeight(height));
289  }
290
291  /// Returns a size that attempts to meet the following conditions, in order:
292  ///
293  ///  * The size must satisfy these constraints.
294  ///  * The aspect ratio of the returned size matches the aspect ratio of the
295  ///    given size.
296  ///  * The returned size as big as possible while still being equal to or
297  ///    smaller than the given size.
298  Size constrainSizeAndAttemptToPreserveAspectRatio(Size size) {
299    if (isTight) {
300      Size result = smallest;
301      assert(() { result = _debugPropagateDebugSize(size, result); return true; }());
302      return result;
303    }
304
305    double width = size.width;
306    double height = size.height;
307    assert(width > 0.0);
308    assert(height > 0.0);
309    final double aspectRatio = width / height;
310
311    if (width > maxWidth) {
312      width = maxWidth;
313      height = width / aspectRatio;
314    }
315
316    if (height > maxHeight) {
317      height = maxHeight;
318      width = height * aspectRatio;
319    }
320
321    if (width < minWidth) {
322      width = minWidth;
323      height = width / aspectRatio;
324    }
325
326    if (height < minHeight) {
327      height = minHeight;
328      width = height * aspectRatio;
329    }
330
331    Size result = Size(constrainWidth(width), constrainHeight(height));
332    assert(() { result = _debugPropagateDebugSize(size, result); return true; }());
333    return result;
334  }
335
336  /// The biggest size that satisfies the constraints.
337  Size get biggest => Size(constrainWidth(), constrainHeight());
338
339  /// The smallest size that satisfies the constraints.
340  Size get smallest => Size(constrainWidth(0.0), constrainHeight(0.0));
341
342  /// Whether there is exactly one width value that satisfies the constraints.
343  bool get hasTightWidth => minWidth >= maxWidth;
344
345  /// Whether there is exactly one height value that satisfies the constraints.
346  bool get hasTightHeight => minHeight >= maxHeight;
347
348  /// Whether there is exactly one size that satisfies the constraints.
349  @override
350  bool get isTight => hasTightWidth && hasTightHeight;
351
352  /// Whether there is an upper bound on the maximum width.
353  ///
354  /// See also:
355  ///
356  ///  * [hasBoundedHeight], the equivalent for the vertical axis.
357  ///  * [hasInfiniteWidth], which describes whether the minimum width
358  ///    constraint is infinite.
359  bool get hasBoundedWidth => maxWidth < double.infinity;
360
361  /// Whether there is an upper bound on the maximum height.
362  ///
363  /// See also:
364  ///
365  ///  * [hasBoundedWidth], the equivalent for the horizontal axis.
366  ///  * [hasInfiniteHeight], which describes whether the minimum height
367  ///    constraint is infinite.
368  bool get hasBoundedHeight => maxHeight < double.infinity;
369
370  /// Whether the width constraint is infinite.
371  ///
372  /// Such a constraint is used to indicate that a box should grow as large as
373  /// some other constraint (in this case, horizontally). If constraints are
374  /// infinite, then they must have other (non-infinite) constraints [enforce]d
375  /// upon them, or must be [tighten]ed, before they can be used to derive a
376  /// [Size] for a [RenderBox.size].
377  ///
378  /// See also:
379  ///
380  ///  * [hasInfiniteHeight], the equivalent for the vertical axis.
381  ///  * [hasBoundedWidth], which describes whether the maximum width
382  ///    constraint is finite.
383  bool get hasInfiniteWidth => minWidth >= double.infinity;
384
385  /// Whether the height constraint is infinite.
386  ///
387  /// Such a constraint is used to indicate that a box should grow as large as
388  /// some other constraint (in this case, vertically). If constraints are
389  /// infinite, then they must have other (non-infinite) constraints [enforce]d
390  /// upon them, or must be [tighten]ed, before they can be used to derive a
391  /// [Size] for a [RenderBox.size].
392  ///
393  /// See also:
394  ///
395  ///  * [hasInfiniteWidth], the equivalent for the horizontal axis.
396  ///  * [hasBoundedHeight], which describes whether the maximum height
397  ///    constraint is finite.
398  bool get hasInfiniteHeight => minHeight >= double.infinity;
399
400  /// Whether the given size satisfies the constraints.
401  bool isSatisfiedBy(Size size) {
402    assert(debugAssertIsValid());
403    return (minWidth <= size.width) && (size.width <= maxWidth) &&
404           (minHeight <= size.height) && (size.height <= maxHeight);
405  }
406
407  /// Scales each constraint parameter by the given factor.
408  BoxConstraints operator*(double factor) {
409    return BoxConstraints(
410      minWidth: minWidth * factor,
411      maxWidth: maxWidth * factor,
412      minHeight: minHeight * factor,
413      maxHeight: maxHeight * factor,
414    );
415  }
416
417  /// Scales each constraint parameter by the inverse of the given factor.
418  BoxConstraints operator/(double factor) {
419    return BoxConstraints(
420      minWidth: minWidth / factor,
421      maxWidth: maxWidth / factor,
422      minHeight: minHeight / factor,
423      maxHeight: maxHeight / factor,
424    );
425  }
426
427  /// Scales each constraint parameter by the inverse of the given factor, rounded to the nearest integer.
428  BoxConstraints operator~/(double factor) {
429    return BoxConstraints(
430      minWidth: (minWidth ~/ factor).toDouble(),
431      maxWidth: (maxWidth ~/ factor).toDouble(),
432      minHeight: (minHeight ~/ factor).toDouble(),
433      maxHeight: (maxHeight ~/ factor).toDouble(),
434    );
435  }
436
437  /// Computes the remainder of each constraint parameter by the given value.
438  BoxConstraints operator%(double value) {
439    return BoxConstraints(
440      minWidth: minWidth % value,
441      maxWidth: maxWidth % value,
442      minHeight: minHeight % value,
443      maxHeight: maxHeight % value,
444    );
445  }
446
447  /// Linearly interpolate between two BoxConstraints.
448  ///
449  /// If either is null, this function interpolates from a [BoxConstraints]
450  /// object whose fields are all set to 0.0.
451  ///
452  /// {@macro dart.ui.shadow.lerp}
453  static BoxConstraints lerp(BoxConstraints a, BoxConstraints b, double t) {
454    assert(t != null);
455    if (a == null && b == null)
456      return null;
457    if (a == null)
458      return b * t;
459    if (b == null)
460      return a * (1.0 - t);
461    assert(a.debugAssertIsValid());
462    assert(b.debugAssertIsValid());
463    assert((a.minWidth.isFinite && b.minWidth.isFinite) || (a.minWidth == double.infinity && b.minWidth == double.infinity), 'Cannot interpolate between finite constraints and unbounded constraints.');
464    assert((a.maxWidth.isFinite && b.maxWidth.isFinite) || (a.maxWidth == double.infinity && b.maxWidth == double.infinity), 'Cannot interpolate between finite constraints and unbounded constraints.');
465    assert((a.minHeight.isFinite && b.minHeight.isFinite) || (a.minHeight == double.infinity && b.minHeight == double.infinity), 'Cannot interpolate between finite constraints and unbounded constraints.');
466    assert((a.maxHeight.isFinite && b.maxHeight.isFinite) || (a.maxHeight == double.infinity && b.maxHeight == double.infinity), 'Cannot interpolate between finite constraints and unbounded constraints.');
467    return BoxConstraints(
468      minWidth: a.minWidth.isFinite ? ui.lerpDouble(a.minWidth, b.minWidth, t) : double.infinity,
469      maxWidth: a.maxWidth.isFinite ? ui.lerpDouble(a.maxWidth, b.maxWidth, t) : double.infinity,
470      minHeight: a.minHeight.isFinite ? ui.lerpDouble(a.minHeight, b.minHeight, t) : double.infinity,
471      maxHeight: a.maxHeight.isFinite ? ui.lerpDouble(a.maxHeight, b.maxHeight, t) : double.infinity,
472    );
473  }
474
475  /// Returns whether the object's constraints are normalized.
476  /// Constraints are normalized if the minimums are less than or
477  /// equal to the corresponding maximums.
478  ///
479  /// For example, a BoxConstraints object with a minWidth of 100.0
480  /// and a maxWidth of 90.0 is not normalized.
481  ///
482  /// Most of the APIs on BoxConstraints expect the constraints to be
483  /// normalized and have undefined behavior when they are not. In
484  /// checked mode, many of these APIs will assert if the constraints
485  /// are not normalized.
486  @override
487  bool get isNormalized {
488    return minWidth >= 0.0 &&
489           minWidth <= maxWidth &&
490           minHeight >= 0.0 &&
491           minHeight <= maxHeight;
492  }
493
494  @override
495  bool debugAssertIsValid({
496    bool isAppliedConstraint = false,
497    InformationCollector informationCollector,
498  }) {
499    assert(() {
500      void throwError(DiagnosticsNode message) {
501        throw FlutterError.fromParts(<DiagnosticsNode>[
502          message,
503          if (informationCollector != null) ...informationCollector(),
504          DiagnosticsProperty<BoxConstraints>('The offending constraints were', this, style: DiagnosticsTreeStyle.errorProperty),
505        ]);
506      }
507      if (minWidth.isNaN || maxWidth.isNaN || minHeight.isNaN || maxHeight.isNaN) {
508        final List<String> affectedFieldsList = <String>[];
509        if (minWidth.isNaN)
510          affectedFieldsList.add('minWidth');
511        if (maxWidth.isNaN)
512          affectedFieldsList.add('maxWidth');
513        if (minHeight.isNaN)
514          affectedFieldsList.add('minHeight');
515        if (maxHeight.isNaN)
516          affectedFieldsList.add('maxHeight');
517        assert(affectedFieldsList.isNotEmpty);
518        if (affectedFieldsList.length > 1)
519          affectedFieldsList.add('and ${affectedFieldsList.removeLast()}');
520        String whichFields = '';
521        if (affectedFieldsList.length > 2) {
522          whichFields = affectedFieldsList.join(', ');
523        } else if (affectedFieldsList.length == 2) {
524          whichFields = affectedFieldsList.join(' ');
525        } else {
526          whichFields = affectedFieldsList.single;
527        }
528        throwError(ErrorSummary('BoxConstraints has ${affectedFieldsList.length == 1 ? 'a NaN value' : 'NaN values' } in $whichFields.'));
529      }
530      if (minWidth < 0.0 && minHeight < 0.0)
531        throwError(ErrorSummary('BoxConstraints has both a negative minimum width and a negative minimum height.'));
532      if (minWidth < 0.0)
533        throwError(ErrorSummary('BoxConstraints has a negative minimum width.'));
534      if (minHeight < 0.0)
535        throwError(ErrorSummary('BoxConstraints has a negative minimum height.'));
536      if (maxWidth < minWidth && maxHeight < minHeight)
537        throwError(ErrorSummary('BoxConstraints has both width and height constraints non-normalized.'));
538      if (maxWidth < minWidth)
539        throwError(ErrorSummary('BoxConstraints has non-normalized width constraints.'));
540      if (maxHeight < minHeight)
541        throwError(ErrorSummary('BoxConstraints has non-normalized height constraints.'));
542      if (isAppliedConstraint) {
543        if (minWidth.isInfinite && minHeight.isInfinite)
544          throwError(ErrorSummary('BoxConstraints forces an infinite width and infinite height.'));
545        if (minWidth.isInfinite)
546          throwError(ErrorSummary('BoxConstraints forces an infinite width.'));
547        if (minHeight.isInfinite)
548          throwError(ErrorSummary('BoxConstraints forces an infinite height.'));
549      }
550      assert(isNormalized);
551      return true;
552    }());
553    return isNormalized;
554  }
555
556  /// Returns a box constraints that [isNormalized].
557  ///
558  /// The returned [maxWidth] is at least as large as the [minWidth]. Similarly,
559  /// the returned [maxHeight] is at least as large as the [minHeight].
560  BoxConstraints normalize() {
561    if (isNormalized)
562      return this;
563    final double minWidth = this.minWidth >= 0.0 ? this.minWidth : 0.0;
564    final double minHeight = this.minHeight >= 0.0 ? this.minHeight : 0.0;
565    return BoxConstraints(
566      minWidth: minWidth,
567      maxWidth: minWidth > maxWidth ? minWidth : maxWidth,
568      minHeight: minHeight,
569      maxHeight: minHeight > maxHeight ? minHeight : maxHeight,
570    );
571  }
572
573  @override
574  bool operator ==(dynamic other) {
575    assert(debugAssertIsValid());
576    if (identical(this, other))
577      return true;
578    if (runtimeType != other.runtimeType)
579      return false;
580    final BoxConstraints typedOther = other;
581    assert(typedOther.debugAssertIsValid());
582    return minWidth == typedOther.minWidth &&
583           maxWidth == typedOther.maxWidth &&
584           minHeight == typedOther.minHeight &&
585           maxHeight == typedOther.maxHeight;
586  }
587
588  @override
589  int get hashCode {
590    assert(debugAssertIsValid());
591    return hashValues(minWidth, maxWidth, minHeight, maxHeight);
592  }
593
594  @override
595  String toString() {
596    final String annotation = isNormalized ? '' : '; NOT NORMALIZED';
597    if (minWidth == double.infinity && minHeight == double.infinity)
598      return 'BoxConstraints(biggest$annotation)';
599    if (minWidth == 0 && maxWidth == double.infinity &&
600        minHeight == 0 && maxHeight == double.infinity)
601      return 'BoxConstraints(unconstrained$annotation)';
602    String describe(double min, double max, String dim) {
603      if (min == max)
604        return '$dim=${min.toStringAsFixed(1)}';
605      return '${min.toStringAsFixed(1)}<=$dim<=${max.toStringAsFixed(1)}';
606    }
607    final String width = describe(minWidth, maxWidth, 'w');
608    final String height = describe(minHeight, maxHeight, 'h');
609    return 'BoxConstraints($width, $height$annotation)';
610  }
611}
612
613/// Method signature for hit testing a [RenderBox].
614///
615/// Used by [BoxHitTestResult.addWithPaintTransform] to hit test children
616/// of a [RenderBox].
617///
618/// See also:
619///
620///  * [RenderBox.hitTest], which documents more details around hit testing
621///    [RenderBox]es.
622typedef BoxHitTest = bool Function(BoxHitTestResult result, Offset position);
623
624/// The result of performing a hit test on [RenderBox]es.
625///
626/// An instance of this class is provided to [RenderBox.hitTest] to record the
627/// result of the hit test.
628class BoxHitTestResult extends HitTestResult {
629  /// Creates an empty hit test result for hit testing on [RenderBox].
630  BoxHitTestResult() : super();
631
632  /// Wraps `result` to create a [HitTestResult] that implements the
633  /// [BoxHitTestResult] protocol for hit testing on [RenderBox]es.
634  ///
635  /// This method is used by [RenderObject]s that adapt between the
636  /// [RenderBox]-world and the non-[RenderBox]-world to convert a (subtype of)
637  /// [HitTestResult] to a [BoxHitTestResult] for hit testing on [RenderBox]es.
638  ///
639  /// The [HitTestEntry] instances added to the returned [BoxHitTestResult] are
640  /// also added to the wrapped `result` (both share the same underlying data
641  /// structure to store [HitTestEntry] instances).
642  ///
643  /// See also:
644  ///
645  ///  * [HitTestResult.wrap], which turns a [BoxHitTestResult] back into a
646  ///    generic [HitTestResult].
647  ///  * [SliverHitTestResult.wrap], which turns a [BoxHitTestResult] into a
648  ///    [SliverHitTestResult] for hit testing on [RenderSliver] children.
649  BoxHitTestResult.wrap(HitTestResult result) : super.wrap(result);
650
651  /// Transforms `position` to the local coordinate system of a child for
652  /// hit-testing the child.
653  ///
654  /// The actual hit testing of the child needs to be implemented in the
655  /// provided `hitTest` callback, which is invoked with the transformed
656  /// `position` as argument.
657  ///
658  /// The provided paint `transform` (which describes the transform from the
659  /// child to the parent in 3D) is processed by
660  /// [PointerEvent.removePerspectiveTransform] to remove the
661  /// perspective component and inverted before it is used to transform
662  /// `position` from the coordinate system of the parent to the system of the
663  /// child.
664  ///
665  /// If `transform` is null it will be treated as the identity transform and
666  /// `position` is provided to the `hitTest` callback as-is. If `transform`
667  /// cannot be inverted, the `hitTest` callback is not invoked and false is
668  /// returned. Otherwise, the return value of the `hitTest` callback is
669  /// returned.
670  ///
671  /// The `position` argument may be null, which will be forwarded to the
672  /// `hitTest` callback as-is. Using null as the position can be useful if
673  /// the child speaks a different hit test protocol then the parent and the
674  /// position is not required to do the actual hit testing in that protocol.
675  ///
676  /// {@tool sample}
677  /// This method is used in [RenderBox.hitTestChildren] when the child and
678  /// parent don't share the same origin.
679  ///
680  /// ```dart
681  /// abstract class Foo extends RenderBox {
682  ///
683  ///   final Matrix4 _effectiveTransform = Matrix4.rotationZ(50);
684  ///
685  ///   @override
686  ///   void applyPaintTransform(RenderBox child, Matrix4 transform) {
687  ///     transform.multiply(_effectiveTransform);
688  ///   }
689  ///
690  ///   @override
691  ///   bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
692  ///     return result.addWithPaintTransform(
693  ///       transform: _effectiveTransform,
694  ///       position: position,
695  ///       hitTest: (BoxHitTestResult result, Offset position) {
696  ///         return super.hitTestChildren(result, position: position);
697  ///       },
698  ///     );
699  ///   }
700  /// }
701  /// ```
702  /// {@end-tool}
703  ///
704  /// See also:
705  ///
706  ///  * [addWithPaintOffset], which can be used for `transform`s that are just
707  ///    simple matrix translations by an [Offset].
708  ///  * [addWithRawTransform], which takes a transform matrix that is directly
709  ///    used to transform the position without any pre-processing.
710  bool addWithPaintTransform({
711    @required Matrix4 transform,
712    @required Offset position,
713    @required BoxHitTest hitTest,
714  }) {
715    assert(hitTest != null);
716    if (transform != null) {
717      transform = Matrix4.tryInvert(PointerEvent.removePerspectiveTransform(transform));
718      if (transform == null) {
719        // Objects are not visible on screen and cannot be hit-tested.
720        return false;
721      }
722    }
723    return addWithRawTransform(
724      transform: transform,
725      position: position,
726      hitTest: hitTest,
727    );
728  }
729
730  /// Convenience method for hit testing children, that are translated by
731  /// an [Offset].
732  ///
733  /// The actual hit testing of the child needs to be implemented in the
734  /// provided `hitTest` callback, which is invoked with the transformed
735  /// `position` as argument.
736  ///
737  /// This method can be used as a convenience over [addWithPaintTransform] if
738  /// a parent paints a child at an `offset`.
739  ///
740  /// A null value for `offset` is treated as if [Offset.zero] was provided.
741  ///
742  /// Se also:
743  ///
744  ///  * [addWithPaintTransform], which takes a generic paint transform matrix and
745  ///    documents the intended usage of this API in more detail.
746  bool addWithPaintOffset({
747    @required Offset offset,
748    @required Offset position,
749    @required BoxHitTest hitTest,
750  }) {
751    assert(hitTest != null);
752    return addWithRawTransform(
753      transform: offset != null ? Matrix4.translationValues(-offset.dx, -offset.dy, 0.0) : null,
754      position: position,
755      hitTest: hitTest,
756    );
757  }
758
759  /// Transforms `position` to the local coordinate system of a child for
760  /// hit-testing the child.
761  ///
762  /// The actual hit testing of the child needs to be implemented in the
763  /// provided `hitTest` callback, which is invoked with the transformed
764  /// `position` as argument.
765  ///
766  /// Unlike [addWithPaintTransform], the provided `transform` matrix is used
767  /// directly to transform `position` without any pre-processing.
768  ///
769  /// If `transform` is null it will be treated as the identity transform ad
770  /// `position` is provided to the `hitTest` callback as-is.
771  ///
772  /// The function returns the return value of the `hitTest` callback.
773  ///
774  /// The `position` argument may be null, which will be forwarded to the
775  /// `hitTest` callback as-is. Using null as the position can be useful if
776  /// the child speaks a different hit test protocol then the parent and the
777  /// position is not required to do the actual hit testing in that protocol.
778  ///
779  /// Se also:
780  ///
781  ///  * [addWithPaintTransform], which accomplishes the same thing, but takes a
782  ///    _paint_ transform matrix.
783  bool addWithRawTransform({
784    @required Matrix4 transform,
785    @required Offset position,
786    @required BoxHitTest hitTest,
787  }) {
788    assert(hitTest != null);
789    final Offset transformedPosition = position == null || transform == null
790        ? position
791        : MatrixUtils.transformPoint(transform, position);
792    if (transform != null) {
793      pushTransform(transform);
794    }
795    final bool isHit = hitTest(this, transformedPosition);
796    if (transform != null) {
797      popTransform();
798    }
799    return isHit;
800  }
801}
802
803/// A hit test entry used by [RenderBox].
804class BoxHitTestEntry extends HitTestEntry {
805  /// Creates a box hit test entry.
806  ///
807  /// The [localPosition] argument must not be null.
808  BoxHitTestEntry(RenderBox target, this.localPosition)
809    : assert(localPosition != null),
810      super(target);
811
812  @override
813  RenderBox get target => super.target;
814
815  /// The position of the hit test in the local coordinates of [target].
816  final Offset localPosition;
817
818  @override
819  String toString() => '${describeIdentity(target)}@$localPosition';
820}
821
822/// Parent data used by [RenderBox] and its subclasses.
823class BoxParentData extends ParentData {
824  /// The offset at which to paint the child in the parent's coordinate system.
825  Offset offset = Offset.zero;
826
827  @override
828  String toString() => 'offset=$offset';
829}
830
831/// Abstract ParentData subclass for RenderBox subclasses that want the
832/// ContainerRenderObjectMixin.
833///
834/// This is a convenience class that mixes in the relevant classes with
835/// the relevant type arguments.
836abstract class ContainerBoxParentData<ChildType extends RenderObject> extends BoxParentData with ContainerParentDataMixin<ChildType> { }
837
838enum _IntrinsicDimension { minWidth, maxWidth, minHeight, maxHeight }
839
840@immutable
841class _IntrinsicDimensionsCacheEntry {
842  const _IntrinsicDimensionsCacheEntry(this.dimension, this.argument);
843
844  final _IntrinsicDimension dimension;
845  final double argument;
846
847  @override
848  bool operator ==(dynamic other) {
849    if (other is! _IntrinsicDimensionsCacheEntry)
850      return false;
851    final _IntrinsicDimensionsCacheEntry typedOther = other;
852    return dimension == typedOther.dimension &&
853           argument == typedOther.argument;
854  }
855
856  @override
857  int get hashCode => hashValues(dimension, argument);
858}
859
860/// A render object in a 2D Cartesian coordinate system.
861///
862/// The [size] of each box is expressed as a width and a height. Each box has
863/// its own coordinate system in which its upper left corner is placed at (0,
864/// 0). The lower right corner of the box is therefore at (width, height). The
865/// box contains all the points including the upper left corner and extending
866/// to, but not including, the lower right corner.
867///
868/// Box layout is performed by passing a [BoxConstraints] object down the tree.
869/// The box constraints establish a min and max value for the child's width and
870/// height. In determining its size, the child must respect the constraints
871/// given to it by its parent.
872///
873/// This protocol is sufficient for expressing a number of common box layout
874/// data flows. For example, to implement a width-in-height-out data flow, call
875/// your child's [layout] function with a set of box constraints with a tight
876/// width value (and pass true for parentUsesSize). After the child determines
877/// its height, use the child's height to determine your size.
878///
879/// ## Writing a RenderBox subclass
880///
881/// One would implement a new [RenderBox] subclass to describe a new layout
882/// model, new paint model, new hit-testing model, or new semantics model, while
883/// remaining in the Cartesian space defined by the [RenderBox] protocol.
884///
885/// To create a new protocol, consider subclassing [RenderObject] instead.
886///
887/// ### Constructors and properties of a new RenderBox subclass
888///
889/// The constructor will typically take a named argument for each property of
890/// the class. The value is then passed to a private field of the class and the
891/// constructor asserts its correctness (e.g. if it should not be null, it
892/// asserts it's not null).
893///
894/// Properties have the form of a getter/setter/field group like the following:
895///
896/// ```dart
897/// AxisDirection get axis => _axis;
898/// AxisDirection _axis;
899/// set axis(AxisDirection value) {
900///   assert(value != null); // same check as in the constructor
901///   if (value == _axis)
902///     return;
903///   _axis = value;
904///   markNeedsLayout();
905/// }
906/// ```
907///
908/// The setter will typically finish with either a call to [markNeedsLayout], if
909/// the layout uses this property, or [markNeedsPaint], if only the painter
910/// function does. (No need to call both, [markNeedsLayout] implies
911/// [markNeedsPaint].)
912///
913/// Consider layout and paint to be expensive; be conservative about calling
914/// [markNeedsLayout] or [markNeedsPaint]. They should only be called if the
915/// layout (or paint, respectively) has actually changed.
916///
917/// ### Children
918///
919/// If a render object is a leaf, that is, it cannot have any children, then
920/// ignore this section. (Examples of leaf render objects are [RenderImage] and
921/// [RenderParagraph].)
922///
923/// For render objects with children, there are four possible scenarios:
924///
925/// * A single [RenderBox] child. In this scenario, consider inheriting from
926///   [RenderProxyBox] (if the render object sizes itself to match the child) or
927///   [RenderShiftedBox] (if the child will be smaller than the box and the box
928///   will align the child inside itself).
929///
930/// * A single child, but it isn't a [RenderBox]. Use the
931///   [RenderObjectWithChildMixin] mixin.
932///
933/// * A single list of children. Use the [ContainerRenderObjectMixin] mixin.
934///
935/// * A more complicated child model.
936///
937/// #### Using RenderProxyBox
938///
939/// By default, a [RenderProxyBox] render object sizes itself to fit its child, or
940/// to be as small as possible if there is no child; it passes all hit testing
941/// and painting on to the child, and intrinsic dimensions and baseline
942/// measurements similarly are proxied to the child.
943///
944/// A subclass of [RenderProxyBox] just needs to override the parts of the
945/// [RenderBox] protocol that matter. For example, [RenderOpacity] just
946/// overrides the paint method (and [alwaysNeedsCompositing] to reflect what the
947/// paint method does, and the [visitChildrenForSemantics] method so that the
948/// child is hidden from accessibility tools when it's invisible), and adds an
949/// [RenderOpacity.opacity] field.
950///
951/// [RenderProxyBox] assumes that the child is the size of the parent and
952/// positioned at 0,0. If this is not true, then use [RenderShiftedBox] instead.
953///
954/// See
955/// [proxy_box.dart](https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/rendering/proxy_box.dart)
956/// for examples of inheriting from [RenderProxyBox].
957///
958/// #### Using RenderShiftedBox
959///
960/// By default, a [RenderShiftedBox] acts much like a [RenderProxyBox] but
961/// without assuming that the child is positioned at 0,0 (the actual position
962/// recorded in the child's [parentData] field is used), and without providing a
963/// default layout algorithm.
964///
965/// See
966/// [shifted_box.dart](https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/rendering/shifted_box.dart)
967/// for examples of inheriting from [RenderShiftedBox].
968///
969/// #### Kinds of children and child-specific data
970///
971/// A [RenderBox] doesn't have to have [RenderBox] children. One can use another
972/// subclass of [RenderObject] for a [RenderBox]'s children. See the discussion
973/// at [RenderObject].
974///
975/// Children can have additional data owned by the parent but stored on the
976/// child using the [parentData] field. The class used for that data must
977/// inherit from [ParentData]. The [setupParentData] method is used to
978/// initialize the [parentData] field of a child when the child is attached.
979///
980/// By convention, [RenderBox] objects that have [RenderBox] children use the
981/// [BoxParentData] class, which has a [BoxParentData.offset] field to store the
982/// position of the child relative to the parent. ([RenderProxyBox] does not
983/// need this offset and therefore is an exception to this rule.)
984///
985/// #### Using RenderObjectWithChildMixin
986///
987/// If a render object has a single child but it isn't a [RenderBox], then the
988/// [RenderObjectWithChildMixin] class, which is a mixin that will handle the
989/// boilerplate of managing a child, will be useful.
990///
991/// It's a generic class with one type argument, the type of the child. For
992/// example, if you are building a `RenderFoo` class which takes a single
993/// `RenderBar` child, you would use the mixin as follows:
994///
995/// ```dart
996/// class RenderFoo extends RenderBox
997///   with RenderObjectWithChildMixin<RenderBar> {
998///   // ...
999/// }
1000/// ```
1001///
1002/// Since the `RenderFoo` class itself is still a [RenderBox] in this case, you
1003/// still have to implement the [RenderBox] layout algorithm, as well as
1004/// features like intrinsics and baselines, painting, and hit testing.
1005///
1006/// #### Using ContainerRenderObjectMixin
1007///
1008/// If a render box can have multiple children, then the
1009/// [ContainerRenderObjectMixin] mixin can be used to handle the boilerplate. It
1010/// uses a linked list to model the children in a manner that is easy to mutate
1011/// dynamically and that can be walked efficiently. Random access is not
1012/// efficient in this model; if you need random access to the children consider
1013/// the next section on more complicated child models.
1014///
1015/// The [ContainerRenderObjectMixin] class has two type arguments. The first is
1016/// the type of the child objects. The second is the type for their
1017/// [parentData]. The class used for [parentData] must itself have the
1018/// [ContainerParentDataMixin] class mixed into it; this is where
1019/// [ContainerRenderObjectMixin] stores the linked list. A [ParentData] class
1020/// can extend [ContainerBoxParentData]; this is essentially
1021/// [BoxParentData] mixed with [ContainerParentDataMixin]. For example, if a
1022/// `RenderFoo` class wanted to have a linked list of [RenderBox] children, one
1023/// might create a `FooParentData` class as follows:
1024///
1025/// ```dart
1026/// class FooParentData extends ContainerBoxParentData<RenderBox> {
1027///   // (any fields you might need for these children)
1028/// }
1029/// ```
1030///
1031/// When using [ContainerRenderObjectMixin] in a [RenderBox], consider mixing in
1032/// [RenderBoxContainerDefaultsMixin], which provides a collection of utility
1033/// methods that implement common parts of the [RenderBox] protocol (such as
1034/// painting the children).
1035///
1036/// The declaration of the `RenderFoo` class itself would thus look like this:
1037///
1038/// ```dart
1039/// class RenderFoo extends RenderBox with
1040///   ContainerRenderObjectMixin<RenderBox, FooParentData>,
1041///   RenderBoxContainerDefaultsMixin<RenderBox, FooParentData> {
1042///   // ...
1043/// }
1044/// ```
1045///
1046/// When walking the children (e.g. during layout), the following pattern is
1047/// commonly used (in this case assuming that the children are all [RenderBox]
1048/// objects and that this render object uses `FooParentData` objects for its
1049/// children's [parentData] fields):
1050///
1051/// ```dart
1052/// RenderBox child = firstChild;
1053/// while (child != null) {
1054///   final FooParentData childParentData = child.parentData;
1055///   // ...operate on child and childParentData...
1056///   assert(child.parentData == childParentData);
1057///   child = childParentData.nextSibling;
1058/// }
1059/// ```
1060///
1061/// #### More complicated child models
1062///
1063/// Render objects can have more complicated models, for example a map of
1064/// children keyed on an enum, or a 2D grid of efficiently randomly-accessible
1065/// children, or multiple lists of children, etc. If a render object has a model
1066/// that can't be handled by the mixins above, it must implement the
1067/// [RenderObject] child protocol, as follows:
1068///
1069/// * Any time a child is removed, call [dropChild] with the child.
1070///
1071/// * Any time a child is added, call [adoptChild] with the child.
1072///
1073/// * Implement the [attach] method such that it calls [attach] on each child.
1074///
1075/// * Implement the [detach] method such that it calls [detach] on each child.
1076///
1077/// * Implement the [redepthChildren] method such that it calls [redepthChild]
1078///   on each child.
1079///
1080/// * Implement the [visitChildren] method such that it calls its argument for
1081///   each child, typically in paint order (back-most to front-most).
1082///
1083/// * Implement [debugDescribeChildren] such that it outputs a [DiagnosticsNode]
1084///   for each child.
1085///
1086/// Implementing these seven bullet points is essentially all that the two
1087/// aforementioned mixins do.
1088///
1089/// ### Layout
1090///
1091/// [RenderBox] classes implement a layout algorithm. They have a set of
1092/// constraints provided to them, and they size themselves based on those
1093/// constraints and whatever other inputs they may have (for example, their
1094/// children or properties).
1095///
1096/// When implementing a [RenderBox] subclass, one must make a choice. Does it
1097/// size itself exclusively based on the constraints, or does it use any other
1098/// information in sizing itself? An example of sizing purely based on the
1099/// constraints would be growing to fit the parent.
1100///
1101/// Sizing purely based on the constraints allows the system to make some
1102/// significant optimizations. Classes that use this approach should override
1103/// [sizedByParent] to return true, and then override [performResize] to set the
1104/// [size] using nothing but the constraints, e.g.:
1105///
1106/// ```dart
1107/// @override
1108/// bool get sizedByParent => true;
1109///
1110/// @override
1111/// void performResize() {
1112///   size = constraints.smallest;
1113/// }
1114/// ```
1115///
1116/// Otherwise, the size is set in the [performLayout] function.
1117///
1118/// The [performLayout] function is where render boxes decide, if they are not
1119/// [sizedByParent], what [size] they should be, and also where they decide
1120/// where their children should be.
1121///
1122/// #### Layout of RenderBox children
1123///
1124/// The [performLayout] function should call the [layout] function of each (box)
1125/// child, passing it a [BoxConstraints] object describing the constraints
1126/// within which the child can render. Passing tight constraints (see
1127/// [BoxConstraints.isTight]) to the child will allow the rendering library to
1128/// apply some optimizations, as it knows that if the constraints are tight, the
1129/// child's dimensions cannot change even if the layout of the child itself
1130/// changes.
1131///
1132/// If the [performLayout] function will use the child's size to affect other
1133/// aspects of the layout, for example if the render box sizes itself around the
1134/// child, or positions several children based on the size of those children,
1135/// then it must specify the `parentUsesSize` argument to the child's [layout]
1136/// function, setting it to true.
1137///
1138/// This flag turns off some optimizations; algorithms that do not rely on the
1139/// children's sizes will be more efficient. (In particular, relying on the
1140/// child's [size] means that if the child is marked dirty for layout, the
1141/// parent will probably also be marked dirty for layout, unless the
1142/// [constraints] given by the parent to the child were tight constraints.)
1143///
1144/// For [RenderBox] classes that do not inherit from [RenderProxyBox], once they
1145/// have laid out their children, they should also position them, by setting the
1146/// [BoxParentData.offset] field of each child's [parentData] object.
1147///
1148/// #### Layout of non-RenderBox children
1149///
1150/// The children of a [RenderBox] do not have to be [RenderBox]es themselves. If
1151/// they use another protocol (as discussed at [RenderObject]), then instead of
1152/// [BoxConstraints], the parent would pass in the appropriate [Constraints]
1153/// subclass, and instead of reading the child's size, the parent would read
1154/// whatever the output of [layout] is for that layout protocol. The
1155/// `parentUsesSize` flag is still used to indicate whether the parent is going
1156/// to read that output, and optimizations still kick in if the child has tight
1157/// constraints (as defined by [Constraints.isTight]).
1158///
1159/// ### Painting
1160///
1161/// To describe how a render box paints, implement the [paint] method. It is
1162/// given a [PaintingContext] object and an [Offset]. The painting context
1163/// provides methods to affect the layer tree as well as a
1164/// [PaintingContext.canvas] which can be used to add drawing commands. The
1165/// canvas object should not be cached across calls to the [PaintingContext]'s
1166/// methods; every time a method on [PaintingContext] is called, there is a
1167/// chance that the canvas will change identity. The offset specifies the
1168/// position of the top left corner of the box in the coordinate system of the
1169/// [PaintingContext.canvas].
1170///
1171/// To draw text on a canvas, use a [TextPainter].
1172///
1173/// To draw an image to a canvas, use the [paintImage] method.
1174///
1175/// A [RenderBox] that uses methods on [PaintingContext] that introduce new
1176/// layers should override the [alwaysNeedsCompositing] getter and set it to
1177/// true. If the object sometimes does and sometimes does not, it can have that
1178/// getter return true in some cases and false in others. In that case, whenever
1179/// the return value would change, call [markNeedsCompositingBitsUpdate]. (This
1180/// is done automatically when a child is added or removed, so you don't have to
1181/// call it explicitly if the [alwaysNeedsCompositing] getter only changes value
1182/// based on the presence or absence of children.)
1183///
1184/// Anytime anything changes on the object that would cause the [paint] method
1185/// to paint something different (but would not cause the layout to change),
1186/// the object should call [markNeedsPaint].
1187///
1188/// #### Painting children
1189///
1190/// The [paint] method's `context` argument has a [PaintingContext.paintChild]
1191/// method, which should be called for each child that is to be painted. It
1192/// should be given a reference to the child, and an [Offset] giving the
1193/// position of the child relative to the parent.
1194///
1195/// If the [paint] method applies a transform to the painting context before
1196/// painting children (or generally applies an additional offset beyond the
1197/// offset it was itself given as an argument), then the [applyPaintTransform]
1198/// method should also be overridden. That method must adjust the matrix that it
1199/// is given in the same manner as it transformed the painting context and
1200/// offset before painting the given child. This is used by the [globalToLocal]
1201/// and [localToGlobal] methods.
1202///
1203/// #### Hit Tests
1204///
1205/// Hit testing for render boxes is implemented by the [hitTest] method. The
1206/// default implementation of this method defers to [hitTestSelf] and
1207/// [hitTestChildren]. When implementing hit testing, you can either override
1208/// these latter two methods, or ignore them and just override [hitTest].
1209///
1210/// The [hitTest] method itself is given an [Offset], and must return true if the
1211/// object or one of its children has absorbed the hit (preventing objects below
1212/// this one from being hit), or false if the hit can continue to other objects
1213/// below this one.
1214///
1215/// For each child [RenderBox], the [hitTest] method on the child should be
1216/// called with the same [HitTestResult] argument and with the point transformed
1217/// into the child's coordinate space (in the same manner that the
1218/// [applyPaintTransform] method would). The default implementation defers to
1219/// [hitTestChildren] to call the children. [RenderBoxContainerDefaultsMixin]
1220/// provides a [RenderBoxContainerDefaultsMixin.defaultHitTestChildren] method
1221/// that does this assuming that the children are axis-aligned, not transformed,
1222/// and positioned according to the [BoxParentData.offset] field of the
1223/// [parentData]; more elaborate boxes can override [hitTestChildren]
1224/// accordingly.
1225///
1226/// If the object is hit, then it should also add itself to the [HitTestResult]
1227/// object that is given as an argument to the [hitTest] method, using
1228/// [HitTestResult.add]. The default implementation defers to [hitTestSelf] to
1229/// determine if the box is hit. If the object adds itself before the children
1230/// can add themselves, then it will be as if the object was above the children.
1231/// If it adds itself after the children, then it will be as if it was below the
1232/// children. Entries added to the [HitTestResult] object should use the
1233/// [BoxHitTestEntry] class. The entries are subsequently walked by the system
1234/// in the order they were added, and for each entry, the target's [handleEvent]
1235/// method is called, passing in the [HitTestEntry] object.
1236///
1237/// Hit testing cannot rely on painting having happened.
1238///
1239/// ### Semantics
1240///
1241/// For a render box to be accessible, implement the
1242/// [describeApproximatePaintClip] and [visitChildrenForSemantics] methods, and
1243/// the [semanticsAnnotator] getter. The default implementations are sufficient
1244/// for objects that only affect layout, but nodes that represent interactive
1245/// components or information (diagrams, text, images, etc) should provide more
1246/// complete implementations. For more information, see the documentation for
1247/// these members.
1248///
1249/// ### Intrinsics and Baselines
1250///
1251/// The layout, painting, hit testing, and semantics protocols are common to all
1252/// render objects. [RenderBox] objects must implement two additional protocols:
1253/// intrinsic sizing and baseline measurements.
1254///
1255/// There are four methods to implement for intrinsic sizing, to compute the
1256/// minimum and maximum intrinsic width and height of the box. The documentation
1257/// for these methods discusses the protocol in detail:
1258/// [computeMinIntrinsicWidth], [computeMaxIntrinsicWidth],
1259/// [computeMinIntrinsicHeight], [computeMaxIntrinsicHeight].
1260///
1261/// In addition, if the box has any children, it must implement
1262/// [computeDistanceToActualBaseline]. [RenderProxyBox] provides a simple
1263/// implementation that forwards to the child; [RenderShiftedBox] provides an
1264/// implementation that offsets the child's baseline information by the position
1265/// of the child relative to the parent. If you do not inherited from either of
1266/// these classes, however, you must implement the algorithm yourself.
1267abstract class RenderBox extends RenderObject {
1268  @override
1269  void setupParentData(covariant RenderObject child) {
1270    if (child.parentData is! BoxParentData)
1271      child.parentData = BoxParentData();
1272  }
1273
1274  Map<_IntrinsicDimensionsCacheEntry, double> _cachedIntrinsicDimensions;
1275
1276  double _computeIntrinsicDimension(_IntrinsicDimension dimension, double argument, double computer(double argument)) {
1277    assert(RenderObject.debugCheckingIntrinsics || !debugDoingThisResize); // performResize should not depend on anything except the incoming constraints
1278    bool shouldCache = true;
1279    assert(() {
1280      // we don't want the checked-mode intrinsic tests to affect
1281      // who gets marked dirty, etc.
1282      if (RenderObject.debugCheckingIntrinsics)
1283        shouldCache = false;
1284      return true;
1285    }());
1286    if (shouldCache) {
1287      _cachedIntrinsicDimensions ??= <_IntrinsicDimensionsCacheEntry, double>{};
1288      return _cachedIntrinsicDimensions.putIfAbsent(
1289        _IntrinsicDimensionsCacheEntry(dimension, argument),
1290        () => computer(argument),
1291      );
1292    }
1293    return computer(argument);
1294  }
1295
1296  /// Returns the minimum width that this box could be without failing to
1297  /// correctly paint its contents within itself, without clipping.
1298  ///
1299  /// The height argument may give a specific height to assume. The given height
1300  /// can be infinite, meaning that the intrinsic width in an unconstrained
1301  /// environment is being requested. The given height should never be negative
1302  /// or null.
1303  ///
1304  /// This function should only be called on one's children. Calling this
1305  /// function couples the child with the parent so that when the child's layout
1306  /// changes, the parent is notified (via [markNeedsLayout]).
1307  ///
1308  /// Calling this function is expensive and as it can result in O(N^2)
1309  /// behavior.
1310  ///
1311  /// Do not override this method. Instead, implement [computeMinIntrinsicWidth].
1312  @mustCallSuper
1313  double getMinIntrinsicWidth(double height) {
1314    assert(() {
1315      if (height == null) {
1316        throw FlutterError.fromParts(<DiagnosticsNode>[
1317          ErrorSummary('The height argument to getMinIntrinsicWidth was null.'),
1318          ErrorDescription('The argument to getMinIntrinsicWidth must not be negative or null.'),
1319          ErrorHint('If you do not have a specific height in mind, then pass double.infinity instead.')
1320        ]);
1321      }
1322      if (height < 0.0) {
1323        throw FlutterError.fromParts(<DiagnosticsNode>[
1324          ErrorSummary('The height argument to getMinIntrinsicWidth was negative.'),
1325          ErrorDescription('The argument to getMinIntrinsicWidth must not be negative or null.'),
1326          ErrorHint(
1327            'If you perform computations on another height before passing it to '
1328            'getMinIntrinsicWidth, consider using math.max() or double.clamp() '
1329            'to force the value into the valid range.'
1330          ),
1331        ]);
1332      }
1333      return true;
1334    }());
1335    return _computeIntrinsicDimension(_IntrinsicDimension.minWidth, height, computeMinIntrinsicWidth);
1336  }
1337
1338  /// Computes the value returned by [getMinIntrinsicWidth]. Do not call this
1339  /// function directly, instead, call [getMinIntrinsicWidth].
1340  ///
1341  /// Override in subclasses that implement [performLayout]. This method should
1342  /// return the minimum width that this box could be without failing to
1343  /// correctly paint its contents within itself, without clipping.
1344  ///
1345  /// If the layout algorithm is independent of the context (e.g. it always
1346  /// tries to be a particular size), or if the layout algorithm is
1347  /// width-in-height-out, or if the layout algorithm uses both the incoming
1348  /// width and height constraints (e.g. it always sizes itself to
1349  /// [BoxConstraints.biggest]), then the `height` argument should be ignored.
1350  ///
1351  /// If the layout algorithm is strictly height-in-width-out, or is
1352  /// height-in-width-out when the width is unconstrained, then the height
1353  /// argument is the height to use.
1354  ///
1355  /// The `height` argument will never be negative or null. It may be infinite.
1356  ///
1357  /// If this algorithm depends on the intrinsic dimensions of a child, the
1358  /// intrinsic dimensions of that child should be obtained using the functions
1359  /// whose names start with `get`, not `compute`.
1360  ///
1361  /// This function should never return a negative or infinite value.
1362  ///
1363  /// ## Examples
1364  ///
1365  /// ### Text
1366  ///
1367  /// Text is the canonical example of a width-in-height-out algorithm. The
1368  /// `height` argument is therefore ignored.
1369  ///
1370  /// Consider the string "Hello World" The _maximum_ intrinsic width (as
1371  /// returned from [computeMaxIntrinsicWidth]) would be the width of the string
1372  /// with no line breaks.
1373  ///
1374  /// The minimum intrinsic width would be the width of the widest word, "Hello"
1375  /// or "World". If the text is rendered in an even narrower width, however, it
1376  /// might still not overflow. For example, maybe the rendering would put a
1377  /// line-break half-way through the words, as in "Hel⁞lo⁞Wor⁞ld". However,
1378  /// this wouldn't be a _correct_ rendering, and [computeMinIntrinsicWidth] is
1379  /// supposed to render the minimum width that the box could be without failing
1380  /// to _correctly_ paint the contents within itself.
1381  ///
1382  /// The minimum intrinsic _height_ for a given width smaller than the minimum
1383  /// intrinsic width could therefore be greater than the minimum intrinsic
1384  /// height for the minimum intrinsic width.
1385  ///
1386  /// ### Viewports (e.g. scrolling lists)
1387  ///
1388  /// Some render boxes are intended to clip their children. For example, the
1389  /// render box for a scrolling list might always size itself to its parents'
1390  /// size (or rather, to the maximum incoming constraints), regardless of the
1391  /// children's sizes, and then clip the children and position them based on
1392  /// the current scroll offset.
1393  ///
1394  /// The intrinsic dimensions in these cases still depend on the children, even
1395  /// though the layout algorithm sizes the box in a way independent of the
1396  /// children. It is the size that is needed to paint the box's contents (in
1397  /// this case, the children) _without clipping_ that matters.
1398  ///
1399  /// ### When the intrinsic dimensions cannot be known
1400  ///
1401  /// There are cases where render objects do not have an efficient way to
1402  /// compute their intrinsic dimensions. For example, it may be prohibitively
1403  /// expensive to reify and measure every child of a lazy viewport (viewports
1404  /// generally only instantiate the actually visible children), or the
1405  /// dimensions may be computed by a callback about which the render object
1406  /// cannot reason.
1407  ///
1408  /// In such cases, it may be impossible (or at least impractical) to actually
1409  /// return a valid answer. In such cases, the intrinsic functions should throw
1410  /// when [RenderObject.debugCheckingIntrinsics] is false and asserts are
1411  /// enabled, and return 0.0 otherwise.
1412  ///
1413  /// See the implementations of [LayoutBuilder] or [RenderViewportBase] for
1414  /// examples (in particular,
1415  /// [RenderViewportBase.debugThrowIfNotCheckingIntrinsics]).
1416  ///
1417  /// ### Aspect-ratio-driven boxes
1418  ///
1419  /// Some boxes always return a fixed size based on the constraints. For these
1420  /// boxes, the intrinsic functions should return the appropriate size when the
1421  /// incoming `height` or `width` argument is finite, treating that as a tight
1422  /// constraint in the respective direction and treating the other direction's
1423  /// constraints as unbounded. This is because the definitions of
1424  /// [computeMinIntrinsicWidth] and [computeMinIntrinsicHeight] are in terms of
1425  /// what the dimensions _could be_, and such boxes can only be one size in
1426  /// such cases.
1427  ///
1428  /// When the incoming argument is not finite, then they should return the
1429  /// actual intrinsic dimensions based on the contents, as any other box would.
1430  @protected
1431  double computeMinIntrinsicWidth(double height) {
1432    return 0.0;
1433  }
1434
1435  /// Returns the smallest width beyond which increasing the width never
1436  /// decreases the preferred height. The preferred height is the value that
1437  /// would be returned by [getMinIntrinsicHeight] for that width.
1438  ///
1439  /// The height argument may give a specific height to assume. The given height
1440  /// can be infinite, meaning that the intrinsic width in an unconstrained
1441  /// environment is being requested. The given height should never be negative
1442  /// or null.
1443  ///
1444  /// This function should only be called on one's children. Calling this
1445  /// function couples the child with the parent so that when the child's layout
1446  /// changes, the parent is notified (via [markNeedsLayout]).
1447  ///
1448  /// Calling this function is expensive and as it can result in O(N^2)
1449  /// behavior.
1450  ///
1451  /// Do not override this method. Instead, implement
1452  /// [computeMaxIntrinsicWidth].
1453  @mustCallSuper
1454  double getMaxIntrinsicWidth(double height) {
1455    assert(() {
1456      if (height == null) {
1457        throw FlutterError.fromParts(<DiagnosticsNode>[
1458          ErrorSummary('The height argument to getMaxIntrinsicWidth was null.'),
1459          ErrorDescription('The argument to getMaxIntrinsicWidth must not be negative or null.'),
1460          ErrorHint('If you do not have a specific height in mind, then pass double.infinity instead.')
1461        ]);
1462      }
1463      if (height < 0.0) {
1464        throw FlutterError.fromParts(<DiagnosticsNode>[
1465          ErrorSummary('The height argument to getMaxIntrinsicWidth was negative.'),
1466          ErrorDescription('The argument to getMaxIntrinsicWidth must not be negative or null.'),
1467          ErrorHint(
1468            'If you perform computations on another height before passing it to '
1469            'getMaxIntrinsicWidth, consider using math.max() or double.clamp() '
1470            'to force the value into the valid range.'
1471          )
1472        ]);
1473      }
1474      return true;
1475    }());
1476    return _computeIntrinsicDimension(_IntrinsicDimension.maxWidth, height, computeMaxIntrinsicWidth);
1477  }
1478
1479  /// Computes the value returned by [getMaxIntrinsicWidth]. Do not call this
1480  /// function directly, instead, call [getMaxIntrinsicWidth].
1481  ///
1482  /// Override in subclasses that implement [performLayout]. This should return
1483  /// the smallest width beyond which increasing the width never decreases the
1484  /// preferred height. The preferred height is the value that would be returned
1485  /// by [computeMinIntrinsicHeight] for that width.
1486  ///
1487  /// If the layout algorithm is strictly height-in-width-out, or is
1488  /// height-in-width-out when the width is unconstrained, then this should
1489  /// return the same value as [computeMinIntrinsicWidth] for the same height.
1490  ///
1491  /// Otherwise, the height argument should be ignored, and the returned value
1492  /// should be equal to or bigger than the value returned by
1493  /// [computeMinIntrinsicWidth].
1494  ///
1495  /// The `height` argument will never be negative or null. It may be infinite.
1496  ///
1497  /// The value returned by this method might not match the size that the object
1498  /// would actually take. For example, a [RenderBox] subclass that always
1499  /// exactly sizes itself using [BoxConstraints.biggest] might well size itself
1500  /// bigger than its max intrinsic size.
1501  ///
1502  /// If this algorithm depends on the intrinsic dimensions of a child, the
1503  /// intrinsic dimensions of that child should be obtained using the functions
1504  /// whose names start with `get`, not `compute`.
1505  ///
1506  /// This function should never return a negative or infinite value.
1507  ///
1508  /// See also examples in the definition of [computeMinIntrinsicWidth].
1509  @protected
1510  double computeMaxIntrinsicWidth(double height) {
1511    return 0.0;
1512  }
1513
1514  /// Returns the minimum height that this box could be without failing to
1515  /// correctly paint its contents within itself, without clipping.
1516  ///
1517  /// The width argument may give a specific width to assume. The given width
1518  /// can be infinite, meaning that the intrinsic height in an unconstrained
1519  /// environment is being requested. The given width should never be negative
1520  /// or null.
1521  ///
1522  /// This function should only be called on one's children. Calling this
1523  /// function couples the child with the parent so that when the child's layout
1524  /// changes, the parent is notified (via [markNeedsLayout]).
1525  ///
1526  /// Calling this function is expensive and as it can result in O(N^2)
1527  /// behavior.
1528  ///
1529  /// Do not override this method. Instead, implement
1530  /// [computeMinIntrinsicHeight].
1531  @mustCallSuper
1532  double getMinIntrinsicHeight(double width) {
1533    assert(() {
1534      if (width == null) {
1535        throw FlutterError.fromParts(<DiagnosticsNode>[
1536          ErrorSummary('The width argument to getMinIntrinsicHeight was null.'),
1537          ErrorDescription('The argument to getMinIntrinsicHeight must not be negative or null.'),
1538          ErrorHint('If you do not have a specific width in mind, then pass double.infinity instead.')
1539        ]);
1540      }
1541      if (width < 0.0) {
1542        throw FlutterError.fromParts(<DiagnosticsNode>[
1543          ErrorSummary('The width argument to getMinIntrinsicHeight was negative.'),
1544          ErrorDescription('The argument to getMinIntrinsicHeight must not be negative or null.'),
1545          ErrorHint(
1546            'If you perform computations on another width before passing it to '
1547            'getMinIntrinsicHeight, consider using math.max() or double.clamp() '
1548            'to force the value into the valid range.'
1549          )
1550        ]);
1551      }
1552      return true;
1553    }());
1554    return _computeIntrinsicDimension(_IntrinsicDimension.minHeight, width, computeMinIntrinsicHeight);
1555  }
1556
1557  /// Computes the value returned by [getMinIntrinsicHeight]. Do not call this
1558  /// function directly, instead, call [getMinIntrinsicHeight].
1559  ///
1560  /// Override in subclasses that implement [performLayout]. Should return the
1561  /// minimum height that this box could be without failing to correctly paint
1562  /// its contents within itself, without clipping.
1563  ///
1564  /// If the layout algorithm is independent of the context (e.g. it always
1565  /// tries to be a particular size), or if the layout algorithm is
1566  /// height-in-width-out, or if the layout algorithm uses both the incoming
1567  /// height and width constraints (e.g. it always sizes itself to
1568  /// [BoxConstraints.biggest]), then the `width` argument should be ignored.
1569  ///
1570  /// If the layout algorithm is strictly width-in-height-out, or is
1571  /// width-in-height-out when the height is unconstrained, then the width
1572  /// argument is the width to use.
1573  ///
1574  /// The `width` argument will never be negative or null. It may be infinite.
1575  ///
1576  /// If this algorithm depends on the intrinsic dimensions of a child, the
1577  /// intrinsic dimensions of that child should be obtained using the functions
1578  /// whose names start with `get`, not `compute`.
1579  ///
1580  /// This function should never return a negative or infinite value.
1581  ///
1582  /// See also examples in the definition of [computeMinIntrinsicWidth].
1583  @protected
1584  double computeMinIntrinsicHeight(double width) {
1585    return 0.0;
1586  }
1587
1588  /// Returns the smallest height beyond which increasing the height never
1589  /// decreases the preferred width. The preferred width is the value that
1590  /// would be returned by [getMinIntrinsicWidth] for that height.
1591  ///
1592  /// The width argument may give a specific width to assume. The given width
1593  /// can be infinite, meaning that the intrinsic height in an unconstrained
1594  /// environment is being requested. The given width should never be negative
1595  /// or null.
1596  ///
1597  /// This function should only be called on one's children. Calling this
1598  /// function couples the child with the parent so that when the child's layout
1599  /// changes, the parent is notified (via [markNeedsLayout]).
1600  ///
1601  /// Calling this function is expensive and as it can result in O(N^2)
1602  /// behavior.
1603  ///
1604  /// Do not override this method. Instead, implement
1605  /// [computeMaxIntrinsicHeight].
1606  @mustCallSuper
1607  double getMaxIntrinsicHeight(double width) {
1608    assert(() {
1609      if (width == null) {
1610        throw FlutterError.fromParts(<DiagnosticsNode>[
1611          ErrorSummary('The width argument to getMaxIntrinsicHeight was null.'),
1612          ErrorDescription('The argument to getMaxIntrinsicHeight must not be negative or null.'),
1613          ErrorHint('If you do not have a specific width in mind, then pass double.infinity instead.')
1614        ]);
1615      }
1616      if (width < 0.0) {
1617        throw FlutterError.fromParts(<DiagnosticsNode>[
1618          ErrorSummary('The width argument to getMaxIntrinsicHeight was negative.'),
1619          ErrorDescription('The argument to getMaxIntrinsicHeight must not be negative or null.'),
1620          ErrorHint(
1621            'If you perform computations on another width before passing it to '
1622            'getMaxIntrinsicHeight, consider using math.max() or double.clamp() '
1623            'to force the value into the valid range.'
1624          )
1625        ]);
1626      }
1627      return true;
1628    }());
1629    return _computeIntrinsicDimension(_IntrinsicDimension.maxHeight, width, computeMaxIntrinsicHeight);
1630  }
1631
1632  /// Computes the value returned by [getMaxIntrinsicHeight]. Do not call this
1633  /// function directly, instead, call [getMaxIntrinsicHeight].
1634  ///
1635  /// Override in subclasses that implement [performLayout]. Should return the
1636  /// smallest height beyond which increasing the height never decreases the
1637  /// preferred width. The preferred width is the value that would be returned
1638  /// by [computeMinIntrinsicWidth] for that height.
1639  ///
1640  /// If the layout algorithm is strictly width-in-height-out, or is
1641  /// width-in-height-out when the height is unconstrained, then this should
1642  /// return the same value as [computeMinIntrinsicHeight] for the same width.
1643  ///
1644  /// Otherwise, the width argument should be ignored, and the returned value
1645  /// should be equal to or bigger than the value returned by
1646  /// [computeMinIntrinsicHeight].
1647  ///
1648  /// The `width` argument will never be negative or null. It may be infinite.
1649  ///
1650  /// The value returned by this method might not match the size that the object
1651  /// would actually take. For example, a [RenderBox] subclass that always
1652  /// exactly sizes itself using [BoxConstraints.biggest] might well size itself
1653  /// bigger than its max intrinsic size.
1654  ///
1655  /// If this algorithm depends on the intrinsic dimensions of a child, the
1656  /// intrinsic dimensions of that child should be obtained using the functions
1657  /// whose names start with `get`, not `compute`.
1658  ///
1659  /// This function should never return a negative or infinite value.
1660  ///
1661  /// See also examples in the definition of [computeMinIntrinsicWidth].
1662  @protected
1663  double computeMaxIntrinsicHeight(double width) {
1664    return 0.0;
1665  }
1666
1667  /// Whether this render object has undergone layout and has a [size].
1668  bool get hasSize => _size != null;
1669
1670  /// The size of this render box computed during layout.
1671  ///
1672  /// This value is stale whenever this object is marked as needing layout.
1673  /// During [performLayout], do not read the size of a child unless you pass
1674  /// true for parentUsesSize when calling the child's [layout] function.
1675  ///
1676  /// The size of a box should be set only during the box's [performLayout] or
1677  /// [performResize] functions. If you wish to change the size of a box outside
1678  /// of those functions, call [markNeedsLayout] instead to schedule a layout of
1679  /// the box.
1680  Size get size {
1681    assert(hasSize, 'RenderBox was not laid out: ${toString()}');
1682    assert(() {
1683      if (_size is _DebugSize) {
1684        final _DebugSize _size = this._size;
1685        assert(_size._owner == this);
1686        if (RenderObject.debugActiveLayout != null) {
1687          // We are always allowed to access our own size (for print debugging
1688          // and asserts if nothing else). Other than us, the only object that's
1689          // allowed to read our size is our parent, if they've said they will.
1690          // If you hit this assert trying to access a child's size, pass
1691          // "parentUsesSize: true" to that child's layout().
1692          assert(debugDoingThisResize || debugDoingThisLayout ||
1693                 (RenderObject.debugActiveLayout == parent && _size._canBeUsedByParent));
1694        }
1695        assert(_size == this._size);
1696      }
1697      return true;
1698    }());
1699    return _size;
1700  }
1701  Size _size;
1702  /// Setting the size, in checked mode, triggers some analysis of the render box,
1703  /// as implemented by [debugAssertDoesMeetConstraints], including calling the intrinsic
1704  /// sizing methods and checking that they meet certain invariants.
1705  @protected
1706  set size(Size value) {
1707    assert(!(debugDoingThisResize && debugDoingThisLayout));
1708    assert(sizedByParent || !debugDoingThisResize);
1709    assert(() {
1710      if ((sizedByParent && debugDoingThisResize) ||
1711          (!sizedByParent && debugDoingThisLayout))
1712        return true;
1713      assert(!debugDoingThisResize);
1714      final List<DiagnosticsNode> information = <DiagnosticsNode>[];
1715      information.add(ErrorSummary('RenderBox size setter called incorrectly.'));
1716      if (debugDoingThisLayout) {
1717        assert(sizedByParent);
1718        information.add(ErrorDescription('It appears that the size setter was called from performLayout().'));
1719      } else {
1720        information.add(ErrorDescription(
1721          'The size setter was called from outside layout (neither performResize() nor performLayout() were being run for this object).'
1722        ));
1723        if (owner != null && owner.debugDoingLayout)
1724          information.add(ErrorDescription('Only the object itself can set its size. It is a contract violation for other objects to set it.'));
1725      }
1726      if (sizedByParent)
1727        information.add(ErrorDescription('Because this RenderBox has sizedByParent set to true, it must set its size in performResize().'));
1728      else
1729        information.add(ErrorDescription('Because this RenderBox has sizedByParent set to false, it must set its size in performLayout().'));
1730      throw FlutterError.fromParts(information);
1731    }());
1732    assert(() {
1733      value = debugAdoptSize(value);
1734      return true;
1735    }());
1736    _size = value;
1737    assert(() {
1738      debugAssertDoesMeetConstraints();
1739      return true;
1740    }());
1741  }
1742
1743  /// Claims ownership of the given [Size].
1744  ///
1745  /// In debug mode, the [RenderBox] class verifies that [Size] objects obtained
1746  /// from other [RenderBox] objects are only used according to the semantics of
1747  /// the [RenderBox] protocol, namely that a [Size] from a [RenderBox] can only
1748  /// be used by its parent, and then only if `parentUsesSize` was set.
1749  ///
1750  /// Sometimes, a [Size] that can validly be used ends up no longer being valid
1751  /// over time. The common example is a [Size] taken from a child that is later
1752  /// removed from the parent. In such cases, this method can be called to first
1753  /// check whether the size can legitimately be used, and if so, to then create
1754  /// a new [Size] that can be used going forward, regardless of what happens to
1755  /// the original owner.
1756  Size debugAdoptSize(Size value) {
1757    Size result = value;
1758    assert(() {
1759      if (value is _DebugSize) {
1760        if (value._owner != this) {
1761          if (value._owner.parent != this) {
1762            throw FlutterError.fromParts(<DiagnosticsNode>[
1763              ErrorSummary('The size property was assigned a size inappropriately.'),
1764              describeForError('The following render object'),
1765              value._owner.describeForError('...was assigned a size obtained from'),
1766              ErrorDescription(
1767                'However, this second render object is not, or is no longer, a '
1768                'child of the first, and it is therefore a violation of the '
1769                'RenderBox layout protocol to use that size in the layout of the '
1770                'first render object.'
1771              ),
1772              ErrorHint(
1773                'If the size was obtained at a time where it was valid to read '
1774                'the size (because the second render object above was a child '
1775                'of the first at the time), then it should be adopted using '
1776                'debugAdoptSize at that time.'
1777              ),
1778              ErrorHint(
1779                'If the size comes from a grandchild or a render object from an '
1780                'entirely different part of the render tree, then there is no '
1781                'way to be notified when the size changes and therefore attempts '
1782                'to read that size are almost certainly a source of bugs. A different '
1783                'approach should be used.'
1784              ),
1785            ]);
1786          }
1787          if (!value._canBeUsedByParent) {
1788            throw FlutterError.fromParts(<DiagnosticsNode>[
1789              ErrorSummary('A child\'s size was used without setting parentUsesSize.'),
1790              describeForError('The following render object'),
1791              value._owner.describeForError('...was assigned a size obtained from its child'),
1792              ErrorDescription(
1793                'However, when the child was laid out, the parentUsesSize argument '
1794                'was not set or set to false. Subsequently this transpired to be '
1795                'inaccurate: the size was nonetheless used by the parent.\n'
1796                'It is important to tell the framework if the size will be used or not '
1797                'as several important performance optimizations can be made if the '
1798                'size will not be used by the parent.'
1799              )
1800            ]);
1801          }
1802        }
1803      }
1804      result = _DebugSize(value, this, debugCanParentUseSize);
1805      return true;
1806    }());
1807    return result;
1808  }
1809
1810  @override
1811  Rect get semanticBounds => Offset.zero & size;
1812
1813  @override
1814  void debugResetSize() {
1815    // updates the value of size._canBeUsedByParent if necessary
1816    size = size;
1817  }
1818
1819  Map<TextBaseline, double> _cachedBaselines;
1820  static bool _debugDoingBaseline = false;
1821  static bool _debugSetDoingBaseline(bool value) {
1822    _debugDoingBaseline = value;
1823    return true;
1824  }
1825
1826  /// Returns the distance from the y-coordinate of the position of the box to
1827  /// the y-coordinate of the first given baseline in the box's contents.
1828  ///
1829  /// Used by certain layout models to align adjacent boxes on a common
1830  /// baseline, regardless of padding, font size differences, etc. If there is
1831  /// no baseline, this function returns the distance from the y-coordinate of
1832  /// the position of the box to the y-coordinate of the bottom of the box
1833  /// (i.e., the height of the box) unless the caller passes true
1834  /// for `onlyReal`, in which case the function returns null.
1835  ///
1836  /// Only call this function after calling [layout] on this box. You
1837  /// are only allowed to call this from the parent of this box during
1838  /// that parent's [performLayout] or [paint] functions.
1839  ///
1840  /// When implementing a [RenderBox] subclass, to override the baseline
1841  /// computation, override [computeDistanceToActualBaseline].
1842  double getDistanceToBaseline(TextBaseline baseline, { bool onlyReal = false }) {
1843    assert(!_debugDoingBaseline, 'Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.');
1844    assert(!debugNeedsLayout);
1845    assert(() {
1846      final RenderObject parent = this.parent;
1847      if (owner.debugDoingLayout)
1848        return (RenderObject.debugActiveLayout == parent) && parent.debugDoingThisLayout;
1849      if (owner.debugDoingPaint)
1850        return ((RenderObject.debugActivePaint == parent) && parent.debugDoingThisPaint) ||
1851               ((RenderObject.debugActivePaint == this) && debugDoingThisPaint);
1852      assert(parent == this.parent);
1853      return false;
1854    }());
1855    assert(_debugSetDoingBaseline(true));
1856    final double result = getDistanceToActualBaseline(baseline);
1857    assert(_debugSetDoingBaseline(false));
1858    if (result == null && !onlyReal)
1859      return size.height;
1860    return result;
1861  }
1862
1863  /// Calls [computeDistanceToActualBaseline] and caches the result.
1864  ///
1865  /// This function must only be called from [getDistanceToBaseline] and
1866  /// [computeDistanceToActualBaseline]. Do not call this function directly from
1867  /// outside those two methods.
1868  @protected
1869  @mustCallSuper
1870  double getDistanceToActualBaseline(TextBaseline baseline) {
1871    assert(_debugDoingBaseline, 'Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.');
1872    _cachedBaselines ??= <TextBaseline, double>{};
1873    _cachedBaselines.putIfAbsent(baseline, () => computeDistanceToActualBaseline(baseline));
1874    return _cachedBaselines[baseline];
1875  }
1876
1877  /// Returns the distance from the y-coordinate of the position of the box to
1878  /// the y-coordinate of the first given baseline in the box's contents, if
1879  /// any, or null otherwise.
1880  ///
1881  /// Do not call this function directly. If you need to know the baseline of a
1882  /// child from an invocation of [performLayout] or [paint], call
1883  /// [getDistanceToBaseline].
1884  ///
1885  /// Subclasses should override this method to supply the distances to their
1886  /// baselines. When implementing this method, there are generally three
1887  /// strategies:
1888  ///
1889  ///  * For classes that use the [ContainerRenderObjectMixin] child model,
1890  ///    consider mixing in the [RenderBoxContainerDefaultsMixin] class and
1891  ///    using
1892  ///    [RenderBoxContainerDefaultsMixin.defaultComputeDistanceToFirstActualBaseline].
1893  ///
1894  ///  * For classes that define a particular baseline themselves, return that
1895  ///    value directly.
1896  ///
1897  ///  * For classes that have a child to which they wish to defer the
1898  ///    computation, call [getDistanceToActualBaseline] on the child (not
1899  ///    [computeDistanceToActualBaseline], the internal implementation, and not
1900  ///    [getDistanceToBaseline], the public entry point for this API).
1901  @protected
1902  double computeDistanceToActualBaseline(TextBaseline baseline) {
1903    assert(_debugDoingBaseline, 'Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.');
1904    return null;
1905  }
1906
1907  /// The box constraints most recently received from the parent.
1908  @override
1909  BoxConstraints get constraints => super.constraints;
1910
1911  @override
1912  void debugAssertDoesMeetConstraints() {
1913    assert(constraints != null);
1914    assert(() {
1915      if (!hasSize) {
1916        assert(!debugNeedsLayout); // this is called in the size= setter during layout, but in that case we have a size
1917        DiagnosticsNode contract;
1918        if (sizedByParent)
1919          contract = ErrorDescription('Because this RenderBox has sizedByParent set to true, it must set its size in performResize().');
1920        else
1921          contract = ErrorDescription('Because this RenderBox has sizedByParent set to false, it must set its size in performLayout().');
1922        throw FlutterError.fromParts(<DiagnosticsNode>[
1923          ErrorSummary('RenderBox did not set its size during layout.'),
1924          contract,
1925          ErrorDescription('It appears that this did not happen; layout completed, but the size property is still null.'),
1926          DiagnosticsProperty<RenderBox>('The RenderBox in question is', this, style: DiagnosticsTreeStyle.errorProperty)
1927        ]);
1928      }
1929      // verify that the size is not infinite
1930      if (!_size.isFinite) {
1931        final List<DiagnosticsNode> information = <DiagnosticsNode>[
1932          ErrorSummary('$runtimeType object was given an infinite size during layout.'),
1933          ErrorDescription(
1934            'This probably means that it is a render object that tries to be '
1935            'as big as possible, but it was put inside another render object '
1936            'that allows its children to pick their own size.'
1937          )
1938        ];
1939        if (!constraints.hasBoundedWidth) {
1940          RenderBox node = this;
1941          while (!node.constraints.hasBoundedWidth && node.parent is RenderBox)
1942            node = node.parent;
1943
1944          information.add(node.describeForError('The nearest ancestor providing an unbounded width constraint is'));
1945        }
1946        if (!constraints.hasBoundedHeight) {
1947          RenderBox node = this;
1948          while (!node.constraints.hasBoundedHeight && node.parent is RenderBox)
1949            node = node.parent;
1950
1951          information.add(node.describeForError('The nearest ancestor providing an unbounded height constraint is'));
1952        }
1953        throw FlutterError.fromParts(<DiagnosticsNode>[
1954          ...information,
1955          DiagnosticsProperty<BoxConstraints>('The constraints that applied to the $runtimeType were', constraints, style: DiagnosticsTreeStyle.errorProperty),
1956          DiagnosticsProperty<Size>('The exact size it was given was', _size, style: DiagnosticsTreeStyle.errorProperty),
1957          ErrorHint('See https://flutter.dev/docs/development/ui/layout/box-constraints for more information.'),
1958        ]);
1959     }
1960      // verify that the size is within the constraints
1961      if (!constraints.isSatisfiedBy(_size)) {
1962        throw FlutterError.fromParts(<DiagnosticsNode>[
1963          ErrorSummary('$runtimeType does not meet its constraints.'),
1964          DiagnosticsProperty<BoxConstraints>('Constraints', constraints, style: DiagnosticsTreeStyle.errorProperty),
1965          DiagnosticsProperty<Size>('Size', _size, style: DiagnosticsTreeStyle.errorProperty),
1966          ErrorHint(
1967            'If you are not writing your own RenderBox subclass, then this is not '
1968            'your fault. Contact support: https://github.com/flutter/flutter/issues/new?template=BUG.md'
1969          ),
1970        ]);
1971      }
1972      if (debugCheckIntrinsicSizes) {
1973        // verify that the intrinsics are sane
1974        assert(!RenderObject.debugCheckingIntrinsics);
1975        RenderObject.debugCheckingIntrinsics = true;
1976        final List<DiagnosticsNode> failures = <DiagnosticsNode>[];
1977
1978        double testIntrinsic(double function(double extent), String name, double constraint) {
1979          final double result = function(constraint);
1980          if (result < 0) {
1981            failures.add(ErrorDescription(' * $name($constraint) returned a negative value: $result'));
1982          }
1983          if (!result.isFinite) {
1984            failures.add(ErrorDescription(' * $name($constraint) returned a non-finite value: $result'));
1985          }
1986          return result;
1987        }
1988
1989        void testIntrinsicsForValues(double getMin(double extent), double getMax(double extent), String name, double constraint) {
1990          final double min = testIntrinsic(getMin, 'getMinIntrinsic$name', constraint);
1991          final double max = testIntrinsic(getMax, 'getMaxIntrinsic$name', constraint);
1992          if (min > max) {
1993            failures.add(ErrorDescription(' * getMinIntrinsic$name($constraint) returned a larger value ($min) than getMaxIntrinsic$name($constraint) ($max)'));
1994          }
1995        }
1996
1997        testIntrinsicsForValues(getMinIntrinsicWidth, getMaxIntrinsicWidth, 'Width', double.infinity);
1998        testIntrinsicsForValues(getMinIntrinsicHeight, getMaxIntrinsicHeight, 'Height', double.infinity);
1999        if (constraints.hasBoundedWidth)
2000          testIntrinsicsForValues(getMinIntrinsicWidth, getMaxIntrinsicWidth, 'Width', constraints.maxHeight);
2001        if (constraints.hasBoundedHeight)
2002          testIntrinsicsForValues(getMinIntrinsicHeight, getMaxIntrinsicHeight, 'Height', constraints.maxWidth);
2003
2004        // TODO(ianh): Test that values are internally consistent in more ways than the above.
2005
2006        RenderObject.debugCheckingIntrinsics = false;
2007        if (failures.isNotEmpty) {
2008          // TODO(jacobr): consider nesting the failures object so it is collapsible.
2009          throw FlutterError.fromParts(<DiagnosticsNode>[
2010            ErrorSummary('The intrinsic dimension methods of the $runtimeType class returned values that violate the intrinsic protocol contract.'),
2011            ErrorDescription('The following ${failures.length > 1 ? "failures" : "failure"} was detected:'), // should this be tagged as an error or not?
2012            ...failures,
2013            ErrorHint(
2014              'If you are not writing your own RenderBox subclass, then this is not\n'
2015              'your fault. Contact support: https://github.com/flutter/flutter/issues/new?template=BUG.md'
2016            ),
2017          ]);
2018        }
2019      }
2020      return true;
2021    }());
2022  }
2023
2024  @override
2025  void markNeedsLayout() {
2026    if ((_cachedBaselines != null && _cachedBaselines.isNotEmpty) ||
2027        (_cachedIntrinsicDimensions != null && _cachedIntrinsicDimensions.isNotEmpty)) {
2028      // If we have cached data, then someone must have used our data.
2029      // Since the parent will shortly be marked dirty, we can forget that they
2030      // used the baseline and/or intrinsic dimensions. If they use them again,
2031      // then we'll fill the cache again, and if we get dirty again, we'll
2032      // notify them again.
2033      _cachedBaselines?.clear();
2034      _cachedIntrinsicDimensions?.clear();
2035      if (parent is RenderObject) {
2036        markParentNeedsLayout();
2037        return;
2038      }
2039    }
2040    super.markNeedsLayout();
2041  }
2042
2043  @override
2044  void performResize() {
2045    // default behavior for subclasses that have sizedByParent = true
2046    size = constraints.smallest;
2047    assert(size.isFinite);
2048  }
2049
2050  @override
2051  void performLayout() {
2052    assert(() {
2053      if (!sizedByParent) {
2054        throw FlutterError.fromParts(<DiagnosticsNode>[
2055          ErrorSummary('$runtimeType did not implement performLayout().'),
2056          ErrorHint(
2057            'RenderBox subclasses need to either override performLayout() to '
2058            'set a size and lay out any children, or, set sizedByParent to true '
2059            'so that performResize() sizes the render object.'
2060          )
2061        ]);
2062      }
2063      return true;
2064    }());
2065  }
2066
2067  /// Determines the set of render objects located at the given position.
2068  ///
2069  /// Returns true, and adds any render objects that contain the point to the
2070  /// given hit test result, if this render object or one of its descendants
2071  /// absorbs the hit (preventing objects below this one from being hit).
2072  /// Returns false if the hit can continue to other objects below this one.
2073  ///
2074  /// The caller is responsible for transforming [position] from global
2075  /// coordinates to its location relative to the origin of this [RenderBox].
2076  /// This [RenderBox] is responsible for checking whether the given position is
2077  /// within its bounds.
2078  ///
2079  /// If transforming is necessary, [BoxHitTestResult.addWithPaintTransform],
2080  /// [BoxHitTestResult.addWithPaintOffset], or
2081  /// [BoxHitTestResult.addWithRawTransform] need to be invoked by the caller
2082  /// to record the required transform operations in the [HitTestResult]. These
2083  /// methods will also help with applying the transform to `position`.
2084  ///
2085  /// Hit testing requires layout to be up-to-date but does not require painting
2086  /// to be up-to-date. That means a render object can rely upon [performLayout]
2087  /// having been called in [hitTest] but cannot rely upon [paint] having been
2088  /// called. For example, a render object might be a child of a [RenderOpacity]
2089  /// object, which calls [hitTest] on its children when its opacity is zero
2090  /// even through it does not [paint] its children.
2091  bool hitTest(BoxHitTestResult result, { @required Offset position }) {
2092    assert(() {
2093      if (!hasSize) {
2094        if (debugNeedsLayout) {
2095          throw FlutterError.fromParts(<DiagnosticsNode>[
2096            ErrorSummary('Cannot hit test a render box that has never been laid out.'),
2097            describeForError('The hitTest() method was called on this RenderBox'),
2098            ErrorDescription(
2099              'Unfortunately, this object\'s geometry is not known at this time, '
2100              'probably because it has never been laid out. '
2101              'This means it cannot be accurately hit-tested.'
2102            ),
2103            ErrorHint(
2104              'If you are trying '
2105              'to perform a hit test during the layout phase itself, make sure '
2106              'you only hit test nodes that have completed layout (e.g. the node\'s '
2107              'children, after their layout() method has been called).'
2108            )
2109          ]);
2110        }
2111        throw FlutterError.fromParts(<DiagnosticsNode>[
2112          ErrorSummary('Cannot hit test a render box with no size.'),
2113          describeForError('The hitTest() method was called on this RenderBox'),
2114          ErrorDescription(
2115            'Although this node is not marked as needing layout, '
2116            'its size is not set.'
2117          ),
2118          ErrorHint(
2119            'A RenderBox object must have an '
2120            'explicit size before it can be hit-tested. Make sure '
2121            'that the RenderBox in question sets its size during layout.'
2122          ),
2123        ]);
2124      }
2125      return true;
2126    }());
2127    if (_size.contains(position)) {
2128      if (hitTestChildren(result, position: position) || hitTestSelf(position)) {
2129        result.add(BoxHitTestEntry(this, position));
2130        return true;
2131      }
2132    }
2133    return false;
2134  }
2135
2136  /// Override this method if this render object can be hit even if its
2137  /// children were not hit.
2138  ///
2139  /// The caller is responsible for transforming [position] from global
2140  /// coordinates to its location relative to the origin of this [RenderBox].
2141  /// This [RenderBox] is responsible for checking whether the given position is
2142  /// within its bounds.
2143  ///
2144  /// Used by [hitTest]. If you override [hitTest] and do not call this
2145  /// function, then you don't need to implement this function.
2146  @protected
2147  bool hitTestSelf(Offset position) => false;
2148
2149  /// Override this method to check whether any children are located at the
2150  /// given position.
2151  ///
2152  /// Typically children should be hit-tested in reverse paint order so that
2153  /// hit tests at locations where children overlap hit the child that is
2154  /// visually "on top" (i.e., paints later).
2155  ///
2156  /// The caller is responsible for transforming [position] from global
2157  /// coordinates to its location relative to the origin of this [RenderBox].
2158  /// This [RenderBox] is responsible for checking whether the given position is
2159  /// within its bounds.
2160  ///
2161  /// If transforming is necessary, [HitTestResult.addWithPaintTransform],
2162  /// [HitTestResult.addWithPaintOffset], or [HitTestResult.addWithRawTransform] need
2163  /// to be invoked by the caller to record the required transform operations
2164  /// in the [HitTestResult]. These methods will also help with applying the
2165  /// transform to `position`.
2166  ///
2167  /// Used by [hitTest]. If you override [hitTest] and do not call this
2168  /// function, then you don't need to implement this function.
2169  @protected
2170  bool hitTestChildren(BoxHitTestResult result, { Offset position }) => false;
2171
2172  /// Multiply the transform from the parent's coordinate system to this box's
2173  /// coordinate system into the given transform.
2174  ///
2175  /// This function is used to convert coordinate systems between boxes.
2176  /// Subclasses that apply transforms during painting should override this
2177  /// function to factor those transforms into the calculation.
2178  ///
2179  /// The [RenderBox] implementation takes care of adjusting the matrix for the
2180  /// position of the given child as determined during layout and stored on the
2181  /// child's [parentData] in the [BoxParentData.offset] field.
2182  @override
2183  void applyPaintTransform(RenderObject child, Matrix4 transform) {
2184    assert(child != null);
2185    assert(child.parent == this);
2186    assert(() {
2187      if (child.parentData is! BoxParentData) {
2188        throw FlutterError.fromParts(<DiagnosticsNode>[
2189          ErrorSummary('$runtimeType does not implement applyPaintTransform.'),
2190          describeForError('The following $runtimeType object'),
2191          child.describeForError('...did not use a BoxParentData class for the parentData field of the following child'),
2192          ErrorDescription('The $runtimeType class inherits from RenderBox.'),
2193          ErrorHint(
2194            'The default applyPaintTransform implementation provided by RenderBox assumes that the '
2195            'children all use BoxParentData objects for their parentData field. '
2196            'Since $runtimeType does not in fact use that ParentData class for its children, it must '
2197            'provide an implementation of applyPaintTransform that supports the specific ParentData '
2198            'subclass used by its children (which apparently is ${child.parentData.runtimeType}).'
2199         )
2200        ]);
2201      }
2202      return true;
2203    }());
2204    final BoxParentData childParentData = child.parentData;
2205    final Offset offset = childParentData.offset;
2206    transform.translate(offset.dx, offset.dy);
2207  }
2208
2209  /// Convert the given point from the global coordinate system in logical pixels
2210  /// to the local coordinate system for this box.
2211  ///
2212  /// This method will un-project the point from the screen onto the widget,
2213  /// which makes it different from [MatrixUtils.transformPoint].
2214  ///
2215  /// If the transform from global coordinates to local coordinates is
2216  /// degenerate, this function returns [Offset.zero].
2217  ///
2218  /// If `ancestor` is non-null, this function converts the given point from the
2219  /// coordinate system of `ancestor` (which must be an ancestor of this render
2220  /// object) instead of from the global coordinate system.
2221  ///
2222  /// This method is implemented in terms of [getTransformTo].
2223  Offset globalToLocal(Offset point, { RenderObject ancestor }) {
2224    // We want to find point (p) that corresponds to a given point on the
2225    // screen (s), but that also physically resides on the local render plane,
2226    // so that it is useful for visually accurate gesture processing in the
2227    // local space. For that, we can't simply transform 2D screen point to
2228    // the 3D local space since the screen space lacks the depth component |z|,
2229    // and so there are many 3D points that correspond to the screen point.
2230    // We must first unproject the screen point onto the render plane to find
2231    // the true 3D point that corresponds to the screen point.
2232    // We do orthogonal unprojection after undoing perspective, in local space.
2233    // The render plane is specified by renderBox offset (o) and Z axis (n).
2234    // Unprojection is done by finding the intersection of the view vector (d)
2235    // with the local X-Y plane: (o-s).dot(n) == (p-s).dot(n), (p-s) == |z|*d.
2236    final Matrix4 transform = getTransformTo(ancestor);
2237    final double det = transform.invert();
2238    if (det == 0.0)
2239      return Offset.zero;
2240    final Vector3 n = Vector3(0.0, 0.0, 1.0);
2241    final Vector3 i = transform.perspectiveTransform(Vector3(0.0, 0.0, 0.0));
2242    final Vector3 d = transform.perspectiveTransform(Vector3(0.0, 0.0, 1.0)) - i;
2243    final Vector3 s = transform.perspectiveTransform(Vector3(point.dx, point.dy, 0.0));
2244    final Vector3 p = s - d * (n.dot(s) / n.dot(d));
2245    return Offset(p.x, p.y);
2246  }
2247
2248  /// Convert the given point from the local coordinate system for this box to
2249  /// the global coordinate system in logical pixels.
2250  ///
2251  /// If `ancestor` is non-null, this function converts the given point to the
2252  /// coordinate system of `ancestor` (which must be an ancestor of this render
2253  /// object) instead of to the global coordinate system.
2254  ///
2255  /// This method is implemented in terms of [getTransformTo].
2256  Offset localToGlobal(Offset point, { RenderObject ancestor }) {
2257    return MatrixUtils.transformPoint(getTransformTo(ancestor), point);
2258  }
2259
2260  /// Returns a rectangle that contains all the pixels painted by this box.
2261  ///
2262  /// The paint bounds can be larger or smaller than [size], which is the amount
2263  /// of space this box takes up during layout. For example, if this box casts a
2264  /// shadow, that shadow might extend beyond the space allocated to this box
2265  /// during layout.
2266  ///
2267  /// The paint bounds are used to size the buffers into which this box paints.
2268  /// If the box attempts to paints outside its paint bounds, there might not be
2269  /// enough memory allocated to represent the box's visual appearance, which
2270  /// can lead to undefined behavior.
2271  ///
2272  /// The returned paint bounds are in the local coordinate system of this box.
2273  @override
2274  Rect get paintBounds => Offset.zero & size;
2275
2276  /// Override this method to handle pointer events that hit this render object.
2277  ///
2278  /// For [RenderBox] objects, the `entry` argument is a [BoxHitTestEntry]. From this
2279  /// object you can determine the [PointerDownEvent]'s position in local coordinates.
2280  /// (This is useful because [PointerEvent.position] is in global coordinates.)
2281  ///
2282  /// If you override this, consider calling [debugHandleEvent] as follows, so
2283  /// that you can support [debugPaintPointersEnabled]:
2284  ///
2285  /// ```dart
2286  /// @override
2287  /// void handleEvent(PointerEvent event, HitTestEntry entry) {
2288  ///   assert(debugHandleEvent(event, entry));
2289  ///   // ... handle the event ...
2290  /// }
2291  /// ```
2292  @override
2293  void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
2294    super.handleEvent(event, entry);
2295  }
2296
2297  int _debugActivePointers = 0;
2298
2299  /// Implements the [debugPaintPointersEnabled] debugging feature.
2300  ///
2301  /// [RenderBox] subclasses that implement [handleEvent] should call
2302  /// [debugHandleEvent] from their [handleEvent] method, as follows:
2303  ///
2304  /// ```dart
2305  /// @override
2306  /// void handleEvent(PointerEvent event, HitTestEntry entry) {
2307  ///   assert(debugHandleEvent(event, entry));
2308  ///   // ... handle the event ...
2309  /// }
2310  /// ```
2311  ///
2312  /// If you call this for a [PointerDownEvent], make sure you also call it for
2313  /// the corresponding [PointerUpEvent] or [PointerCancelEvent].
2314  bool debugHandleEvent(PointerEvent event, HitTestEntry entry) {
2315    assert(() {
2316      if (debugPaintPointersEnabled) {
2317        if (event is PointerDownEvent) {
2318          _debugActivePointers += 1;
2319        } else if (event is PointerUpEvent || event is PointerCancelEvent) {
2320          _debugActivePointers -= 1;
2321        }
2322        markNeedsPaint();
2323      }
2324      return true;
2325    }());
2326    return true;
2327  }
2328
2329  @override
2330  void debugPaint(PaintingContext context, Offset offset) {
2331    assert(() {
2332      if (debugPaintSizeEnabled)
2333        debugPaintSize(context, offset);
2334      if (debugPaintBaselinesEnabled)
2335        debugPaintBaselines(context, offset);
2336      if (debugPaintPointersEnabled)
2337        debugPaintPointers(context, offset);
2338      return true;
2339    }());
2340  }
2341
2342  /// In debug mode, paints a border around this render box.
2343  ///
2344  /// Called for every [RenderBox] when [debugPaintSizeEnabled] is true.
2345  @protected
2346  void debugPaintSize(PaintingContext context, Offset offset) {
2347    assert(() {
2348      final Paint paint = Paint()
2349       ..style = PaintingStyle.stroke
2350       ..strokeWidth = 1.0
2351       ..color = const Color(0xFF00FFFF);
2352      context.canvas.drawRect((offset & size).deflate(0.5), paint);
2353      return true;
2354    }());
2355  }
2356
2357  /// In debug mode, paints a line for each baseline.
2358  ///
2359  /// Called for every [RenderBox] when [debugPaintBaselinesEnabled] is true.
2360  @protected
2361  void debugPaintBaselines(PaintingContext context, Offset offset) {
2362    assert(() {
2363      final Paint paint = Paint()
2364       ..style = PaintingStyle.stroke
2365       ..strokeWidth = 0.25;
2366      Path path;
2367      // ideographic baseline
2368      final double baselineI = getDistanceToBaseline(TextBaseline.ideographic, onlyReal: true);
2369      if (baselineI != null) {
2370        paint.color = const Color(0xFFFFD000);
2371        path = Path();
2372        path.moveTo(offset.dx, offset.dy + baselineI);
2373        path.lineTo(offset.dx + size.width, offset.dy + baselineI);
2374        context.canvas.drawPath(path, paint);
2375      }
2376      // alphabetic baseline
2377      final double baselineA = getDistanceToBaseline(TextBaseline.alphabetic, onlyReal: true);
2378      if (baselineA != null) {
2379        paint.color = const Color(0xFF00FF00);
2380        path = Path();
2381        path.moveTo(offset.dx, offset.dy + baselineA);
2382        path.lineTo(offset.dx + size.width, offset.dy + baselineA);
2383        context.canvas.drawPath(path, paint);
2384      }
2385      return true;
2386    }());
2387  }
2388
2389  /// In debug mode, paints a rectangle if this render box has counted more
2390  /// pointer downs than pointer up events.
2391  ///
2392  /// Called for every [RenderBox] when [debugPaintPointersEnabled] is true.
2393  ///
2394  /// By default, events are not counted. For details on how to ensure that
2395  /// events are counted for your class, see [debugHandleEvent].
2396  @protected
2397  void debugPaintPointers(PaintingContext context, Offset offset) {
2398    assert(() {
2399      if (_debugActivePointers > 0) {
2400        final Paint paint = Paint()
2401         ..color = Color(0x00BBBB | ((0x04000000 * depth) & 0xFF000000));
2402        context.canvas.drawRect(offset & size, paint);
2403      }
2404      return true;
2405    }());
2406  }
2407
2408  @override
2409  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
2410    super.debugFillProperties(properties);
2411    properties.add(DiagnosticsProperty<Size>('size', _size, missingIfNull: true));
2412  }
2413}
2414
2415/// A mixin that provides useful default behaviors for boxes with children
2416/// managed by the [ContainerRenderObjectMixin] mixin.
2417///
2418/// By convention, this class doesn't override any members of the superclass.
2419/// Instead, it provides helpful functions that subclasses can call as
2420/// appropriate.
2421mixin RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, ParentDataType extends ContainerBoxParentData<ChildType>> implements ContainerRenderObjectMixin<ChildType, ParentDataType> {
2422  /// Returns the baseline of the first child with a baseline.
2423  ///
2424  /// Useful when the children are displayed vertically in the same order they
2425  /// appear in the child list.
2426  double defaultComputeDistanceToFirstActualBaseline(TextBaseline baseline) {
2427    assert(!debugNeedsLayout);
2428    ChildType child = firstChild;
2429    while (child != null) {
2430      final ParentDataType childParentData = child.parentData;
2431      final double result = child.getDistanceToActualBaseline(baseline);
2432      if (result != null)
2433        return result + childParentData.offset.dy;
2434      child = childParentData.nextSibling;
2435    }
2436    return null;
2437  }
2438
2439  /// Returns the minimum baseline value among every child.
2440  ///
2441  /// Useful when the vertical position of the children isn't determined by the
2442  /// order in the child list.
2443  double defaultComputeDistanceToHighestActualBaseline(TextBaseline baseline) {
2444    assert(!debugNeedsLayout);
2445    double result;
2446    ChildType child = firstChild;
2447    while (child != null) {
2448      final ParentDataType childParentData = child.parentData;
2449      double candidate = child.getDistanceToActualBaseline(baseline);
2450      if (candidate != null) {
2451        candidate += childParentData.offset.dy;
2452        if (result != null)
2453          result = math.min(result, candidate);
2454        else
2455          result = candidate;
2456      }
2457      child = childParentData.nextSibling;
2458    }
2459    return result;
2460  }
2461
2462  /// Performs a hit test on each child by walking the child list backwards.
2463  ///
2464  /// Stops walking once after the first child reports that it contains the
2465  /// given point. Returns whether any children contain the given point.
2466  ///
2467  /// See also:
2468  ///
2469  ///  * [defaultPaint], which paints the children appropriate for this
2470  ///    hit-testing strategy.
2471  bool defaultHitTestChildren(BoxHitTestResult result, { Offset position }) {
2472    // the x, y parameters have the top left of the node's box as the origin
2473    ChildType child = lastChild;
2474    while (child != null) {
2475      final ParentDataType childParentData = child.parentData;
2476      final bool isHit = result.addWithPaintOffset(
2477        offset: childParentData.offset,
2478        position: position,
2479        hitTest: (BoxHitTestResult result, Offset transformed) {
2480          assert(transformed == position - childParentData.offset);
2481          return child.hitTest(result, position: transformed);
2482        },
2483      );
2484      if (isHit)
2485        return true;
2486      child = childParentData.previousSibling;
2487    }
2488    return false;
2489  }
2490
2491  /// Paints each child by walking the child list forwards.
2492  ///
2493  /// See also:
2494  ///
2495  ///  * [defaultHitTestChildren], which implements hit-testing of the children
2496  ///    in a manner appropriate for this painting strategy.
2497  void defaultPaint(PaintingContext context, Offset offset) {
2498    ChildType child = firstChild;
2499    while (child != null) {
2500      final ParentDataType childParentData = child.parentData;
2501      context.paintChild(child, childParentData.offset + offset);
2502      child = childParentData.nextSibling;
2503    }
2504  }
2505
2506  /// Returns a list containing the children of this render object.
2507  ///
2508  /// This function is useful when you need random-access to the children of
2509  /// this render object. If you're accessing the children in order, consider
2510  /// walking the child list directly.
2511  List<ChildType> getChildrenAsList() {
2512    final List<ChildType> result = <ChildType>[];
2513    RenderBox child = firstChild;
2514    while (child != null) {
2515      final ParentDataType childParentData = child.parentData;
2516      result.add(child);
2517      child = childParentData.nextSibling;
2518    }
2519    return result;
2520  }
2521}
2522