LCOV - code coverage report
Current view: top level - menu - mongol_instrinsic_height.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 53 70 75.7 %
Date: 2021-08-02 17:55:49 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2014 The Flutter Authors.
       2             : // Copyright 2021 Suragch.
       3             : // All rights reserved.
       4             : // Use of this source code is governed by a BSD-style license that can be
       5             : // found in the LICENSE file.
       6             : 
       7             : import 'package:flutter/foundation.dart';
       8             : import 'package:flutter/rendering.dart';
       9             : import 'package:flutter/widgets.dart';
      10             : 
      11             : /// A widget that sizes its child to the child's maximum intrinsic height.
      12             : ///
      13             : /// This class is useful, for example, when unlimited height is available and
      14             : /// you would like a child that would otherwise attempt to expand infinitely to
      15             : /// instead size itself to a more reasonable height.
      16             : ///
      17             : /// The constraints that this widget passes to its child will adhere to the
      18             : /// parent's constraints, so if the constraints are not large enough to satisfy
      19             : /// the child's maximum intrinsic height, then the child will get less height
      20             : /// than it otherwise would. Likewise, if the minimum height constraint is
      21             : /// larger than the child's maximum intrinsic height, the child will be given
      22             : /// more width than it otherwise would.
      23             : ///
      24             : /// If [stepHeight] is non-null, the child's height will be snapped to a multiple
      25             : /// of the [stepHeight]. Similarly, if [stepWidth] is non-null, the child's
      26             : /// width will be snapped to a multiple of the [stepWidth].
      27             : ///
      28             : /// This class is relatively expensive, because it adds a speculative layout
      29             : /// pass before the final layout phase. Avoid using it where possible. In the
      30             : /// worst case, this widget can result in a layout that is O(N²) in the depth of
      31             : /// the tree.
      32             : ///
      33             : /// See also:
      34             : ///
      35             : ///  * [Align], a widget that aligns its child within itself. This can be used
      36             : ///    to loosen the constraints passed to the [MongolRenderIntrinsicHeight],
      37             : ///    allowing the [MongolRenderIntrinsicHeight]'s child to be smaller than that of
      38             : ///    its parent.
      39             : ///  * [Column], which when used with [CrossAxisAlignment.stretch] can be used
      40             : ///    to loosen just the height constraints that are passed to the
      41             : ///    [MongolRenderIntrinsicHeight], allowing the [MongolRenderIntrinsicHeight]'s child's
      42             : ///    height to be smaller than that of its parent.
      43             : class MongolIntrinsicHeight extends SingleChildRenderObjectWidget {
      44             :   /// Creates a widget that sizes its child to the child's intrinsic height.
      45             :   ///
      46             :   /// This class is relatively expensive. Avoid using it where possible.
      47           1 :   const MongolIntrinsicHeight(
      48             :       {Key? key, this.stepHeight, this.stepWidth, Widget? child})
      49           1 :       : assert(stepHeight == null || stepHeight >= 0.0),
      50           0 :         assert(stepWidth == null || stepWidth >= 0.0),
      51           1 :         super(key: key, child: child);
      52             : 
      53             :   /// If non-null, force the child's height to be a multiple of this value.
      54             :   ///
      55             :   /// If null or 0.0 the child's height will be the same as its maximum
      56             :   /// intrinsic height.
      57             :   ///
      58             :   /// This value must not be negative.
      59             :   ///
      60             :   /// See also:
      61             :   ///
      62             :   ///  * [RenderBox.getMaxIntrinsicHeight], which defines a widget's max
      63             :   ///    intrinsic height  in general.
      64             :   final double? stepHeight;
      65             : 
      66             :   /// If non-null, force the child's width to be a multiple of this value.
      67             :   ///
      68             :   /// If null or 0.0 the child's width will not be constrained.
      69             :   ///
      70             :   /// This value must not be negative.
      71             :   final double? stepWidth;
      72             : 
      73           4 :   double? get _stepHeight => stepHeight == 0.0 ? null : stepHeight;
      74           4 :   double? get _stepWidth => stepWidth == 0.0 ? null : stepWidth;
      75             : 
      76           1 :   @override
      77             :   MongolRenderIntrinsicHeight createRenderObject(BuildContext context) {
      78           1 :     return MongolRenderIntrinsicHeight(
      79           2 :         stepHeight: _stepHeight, stepWidth: _stepWidth);
      80             :   }
      81             : 
      82           1 :   @override
      83             :   void updateRenderObject(
      84             :       BuildContext context, MongolRenderIntrinsicHeight renderObject) {
      85             :     renderObject
      86           2 :       ..stepHeight = _stepHeight
      87           2 :       ..stepWidth = _stepWidth;
      88             :   }
      89             : }
      90             : 
      91             : /// Sizes its child to the child's maximum intrinsic height.
      92             : ///
      93             : /// This class is useful, for example, when unlimited height is available and
      94             : /// you would like a child that would otherwise attempt to expand infinitely to
      95             : /// instead size itself to a more reasonable height.
      96             : ///
      97             : /// The constraints that this widget passes to its child will adhere to the
      98             : /// parent's constraints, so if the constraints are not large enough to satisfy
      99             : /// the child's maximum intrinsic height, then the child will get less height
     100             : /// than it otherwise would. Likewise, if the minimum height constraint is
     101             : /// larger than the child's maximum intrinsic height, the child will be given
     102             : /// more width than it otherwise would.
     103             : ///
     104             : /// If [stepHeight] is non-null, the child's height will be snapped to a multiple
     105             : /// of the [stepHeight]. Similarly, if [stepWidth] is non-null, the child's
     106             : /// width will be snapped to a multiple of the [stepWidth].
     107             : ///
     108             : /// This class is relatively expensive, because it adds a speculative layout
     109             : /// pass before the final layout phase. Avoid using it where possible. In the
     110             : /// worst case, this widget can result in a layout that is O(N²) in the depth of
     111             : /// the tree.
     112             : ///
     113             : /// See also:
     114             : ///
     115             : ///  * [Align], a widget that aligns its child within itself. This can be used
     116             : ///    to loosen the constraints passed to the [MongolRenderIntrinsicHeight],
     117             : ///    allowing the [MongolRenderIntrinsicHeight]'s child to be smaller than that of
     118             : ///    its parent.
     119             : ///  * [Column], which when used with [CrossAxisAlignment.stretch] can be used
     120             : ///    to loosen just the height constraints that are passed to the
     121             : ///    [MongolRenderIntrinsicHeight], allowing the [MongolRenderIntrinsicHeight]'s child's
     122             : ///    height to be smaller than that of its parent.
     123             : class MongolRenderIntrinsicHeight extends RenderProxyBox {
     124             :   /// Creates a render object that sizes itself to its child's intrinsic height.
     125             :   ///
     126             :   /// If [stepHeight] is non-null it must be > 0.0. Similarly If [stepWidth] is
     127             :   /// non-null it must be > 0.0.
     128           1 :   MongolRenderIntrinsicHeight({
     129             :     double? stepHeight,
     130             :     double? stepWidth,
     131             :     RenderBox? child,
     132           1 :   })  : assert(stepHeight == null || stepHeight > 0.0),
     133           0 :         assert(stepWidth == null || stepWidth > 0.0),
     134             :         _stepHeight = stepHeight,
     135             :         _stepWidth = stepWidth,
     136           1 :         super(child);
     137             : 
     138             :   /// If non-null, force the child's height to be a multiple of this value.
     139             :   ///
     140             :   /// This value must be null or > 0.0.
     141           0 :   double? get stepHeight => _stepHeight;
     142             :   double? _stepHeight;
     143           1 :   set stepHeight(double? value) {
     144           1 :     assert(value == null || value > 0.0);
     145           2 :     if (value == _stepHeight) return;
     146           0 :     _stepHeight = value;
     147           0 :     markNeedsLayout();
     148             :   }
     149             : 
     150             :   /// If non-null, force the child's width to be a multiple of this value.
     151             :   ///
     152             :   /// This value must be null or > 0.0.
     153           0 :   double? get stepWidth => _stepWidth;
     154             :   double? _stepWidth;
     155           1 :   set stepWidth(double? value) {
     156           0 :     assert(value == null || value > 0.0);
     157           2 :     if (value == _stepWidth) return;
     158           0 :     _stepWidth = value;
     159           0 :     markNeedsLayout();
     160             :   }
     161             : 
     162           1 :   static double _applyStep(double input, double? step) {
     163           1 :     assert(input.isFinite);
     164             :     if (step == null) return input;
     165           3 :     return (input / step).ceil() * step;
     166             :   }
     167             : 
     168           1 :   @override
     169             :   double computeMinIntrinsicHeight(double width) {
     170           1 :     return computeMaxIntrinsicHeight(width);
     171             :   }
     172             : 
     173           1 :   @override
     174             :   double computeMaxIntrinsicHeight(double width) {
     175           1 :     if (child == null) return 0.0;
     176           2 :     final double height = child!.getMaxIntrinsicHeight(width);
     177           2 :     return _applyStep(height, _stepHeight);
     178             :   }
     179             : 
     180           1 :   @override
     181             :   double computeMinIntrinsicWidth(double height) {
     182           1 :     if (child == null) return 0.0;
     183           2 :     if (!height.isFinite) height = computeMaxIntrinsicHeight(double.infinity);
     184           1 :     assert(height.isFinite);
     185           2 :     final double width = child!.getMinIntrinsicWidth(height);
     186           2 :     return _applyStep(width, _stepWidth);
     187             :   }
     188             : 
     189           1 :   @override
     190             :   double computeMaxIntrinsicWidth(double height) {
     191           1 :     if (child == null) return 0.0;
     192           2 :     if (!height.isFinite) height = computeMaxIntrinsicHeight(double.infinity);
     193           1 :     assert(height.isFinite);
     194           2 :     final double width = child!.getMaxIntrinsicWidth(height);
     195           2 :     return _applyStep(width, _stepWidth);
     196             :   }
     197             : 
     198           1 :   Size _computeSize(
     199             :       {required ChildLayouter layoutChild,
     200             :       required BoxConstraints constraints}) {
     201           1 :     if (child != null) {
     202           1 :       if (!constraints.hasTightHeight) {
     203             :         final double height =
     204           3 :             child!.getMaxIntrinsicHeight(constraints.maxWidth);
     205           1 :         assert(height.isFinite);
     206             :         constraints =
     207           3 :             constraints.tighten(height: _applyStep(height, _stepHeight));
     208             :       }
     209           1 :       if (_stepWidth != null) {
     210           0 :         final double width = child!.getMaxIntrinsicWidth(constraints.maxHeight);
     211           0 :         assert(width.isFinite);
     212           0 :         constraints = constraints.tighten(width: _applyStep(width, _stepWidth));
     213             :       }
     214           2 :       return layoutChild(child!, constraints);
     215             :     } else {
     216           0 :       return constraints.smallest;
     217             :     }
     218             :   }
     219             : 
     220           1 :   @override
     221             :   Size computeDryLayout(BoxConstraints constraints) {
     222           1 :     return _computeSize(
     223             :       layoutChild: ChildLayoutHelper.dryLayoutChild,
     224             :       constraints: constraints,
     225             :     );
     226             :   }
     227             : 
     228           1 :   @override
     229             :   void performLayout() {
     230           2 :     size = _computeSize(
     231             :       layoutChild: ChildLayoutHelper.layoutChild,
     232           1 :       constraints: constraints,
     233             :     );
     234             :   }
     235             : 
     236           0 :   @override
     237             :   void debugFillProperties(DiagnosticPropertiesBuilder properties) {
     238           0 :     super.debugFillProperties(properties);
     239           0 :     properties.add(DoubleProperty('stepHeight', stepHeight));
     240           0 :     properties.add(DoubleProperty('stepWidth', stepWidth));
     241             :   }
     242             : }

Generated by: LCOV version 1.15