示例#1
0
        float _pointerSignalEventDelta(PointerScrollEvent evt)
        {
            float delta = widget.axis == Axis.horizontal
                ? evt.scrollDelta.dx
                : evt.scrollDelta.dy;

            if (AxisUtils.axisDirectionIsReversed(widget.axisDirection))
            {
                delta *= -1;
            }
            return(delta);
        }
示例#2
0
        public static AxisDirection applyGrowthDirectionToAxisDirection(
            AxisDirection axisDirection, GrowthDirection growthDirection)
        {
            switch (growthDirection)
            {
            case GrowthDirection.forward:
                return(axisDirection);

            case GrowthDirection.reverse:
                return(AxisUtils.flipAxisDirection(axisDirection));
            }

            throw new Exception("unknown growthDirection");
        }
示例#3
0
        float _targetScrollOffsetForPointerScroll(PointerScrollEvent e)
        {
            float delta = widget.axis == Axis.horizontal
                ? e.scrollDelta.dx
                : e.scrollDelta.dy;

            if (AxisUtils.axisDirectionIsReversed(widget.axisDirection))
            {
                delta *= -1;
            }

            return(Mathf.Min(Mathf.Max(position.pixels + delta, position.minScrollExtent),
                             position.maxScrollExtent));
        }
示例#4
0
        public override SliverGridLayout getLayout(SliverConstraints constraints)
        {
            float tileWidth =
                (constraints.crossAxisExtent -
                 (material_._yearPickerColumnCount - 1) * material_._yearPickerRowSpacing) /
                material_._yearPickerColumnCount;

            return(new SliverGridRegularTileLayout(
                       childCrossAxisExtent: tileWidth,
                       childMainAxisExtent: material_._yearPickerRowHeight,
                       crossAxisCount: material_._yearPickerColumnCount,
                       crossAxisStride: tileWidth + material_._yearPickerRowSpacing,
                       mainAxisStride: material_._yearPickerRowHeight,
                       reverseCrossAxis: AxisUtils.axisDirectionIsReversed(constraints.crossAxisDirection)
                       ));
        }
示例#5
0
        public override SliverGridLayout getLayout(SliverConstraints constraints)
        {
            const int columnCount = daysPerWeek;
            float     tileWidth   = constraints.crossAxisExtent / columnCount;
            float     tileHeight  = Mathf.Min(material_._dayPickerRowHeight,
                                              constraints.viewportMainAxisExtent / material_._maxDayPickerRowCount);

            return(new SliverGridRegularTileLayout(
                       childCrossAxisExtent: tileWidth,
                       childMainAxisExtent: tileHeight,
                       crossAxisCount: columnCount,
                       crossAxisStride: tileWidth,
                       mainAxisStride: tileHeight,
                       reverseCrossAxis: AxisUtils.axisDirectionIsReversed(constraints.crossAxisDirection)
                       ));
        }
示例#6
0
        AxisDirection?_getDirection(BuildContext context)
        {
            switch (widget.scrollDirection)
            {
            case Axis.horizontal:
                D.assert(WidgetsD.debugCheckHasDirectionality(context));
                TextDirection textDirection = Directionality.of(context);
                AxisDirection?axisDirection = AxisUtils.textDirectionToAxisDirection(textDirection);
                return(widget.reverse ? AxisUtils.flipAxisDirection(axisDirection) : axisDirection);

            case Axis.vertical:
                return(widget.reverse ? AxisDirection.up : AxisDirection.down);
            }

            throw new UIWidgetsError("fail to get axis direction");
        }
示例#7
0
        public static AxisDirection?applyGrowthDirectionToAxisDirection(
            AxisDirection?axisDirection, GrowthDirection?growthDirection)
        {
            D.assert(axisDirection != null);
            D.assert(growthDirection != null);
            switch (growthDirection)
            {
            case GrowthDirection.forward:
                return(axisDirection);

            case GrowthDirection.reverse:
                return(AxisUtils.flipAxisDirection(axisDirection));
            }

            throw new Exception("unknown growthDirection");
        }
        public override SliverGridLayout getLayout(SliverConstraints constraints)
        {
            D.assert(this._debugAssertIsValid());
            float usableCrossAxisExtent =
                constraints.crossAxisExtent - this.crossAxisSpacing * (this.crossAxisCount - 1);
            float childCrossAxisExtent = usableCrossAxisExtent / this.crossAxisCount;
            float childMainAxisExtent  = childCrossAxisExtent / this.childAspectRatio;

            return(new SliverGridRegularTileLayout(
                       crossAxisCount: this.crossAxisCount,
                       mainAxisStride: childMainAxisExtent + this.mainAxisSpacing,
                       crossAxisStride: childCrossAxisExtent + this.crossAxisSpacing,
                       childMainAxisExtent: childMainAxisExtent,
                       childCrossAxisExtent: childCrossAxisExtent,
                       reverseCrossAxis: AxisUtils.axisDirectionIsReversed(constraints.crossAxisDirection)
                       ));
        }
示例#9
0
        public override SliverGridLayout getLayout(SliverConstraints constraints)
        {
            const int columnCount = 7; // DateTime.daysPerWeek = 7
            float     tileWidth   = constraints.crossAxisExtent / columnCount;
            float     tileHeight  = Mathf.Min(
                DatePickerUtils._kDayPickerRowHeight,
                constraints.viewportMainAxisExtent / (DatePickerUtils._kMaxDayPickerRowCount + 1)
                );

            return(new SliverGridRegularTileLayout(
                       crossAxisCount: columnCount,
                       mainAxisStride: tileHeight,
                       crossAxisStride: tileWidth,
                       childMainAxisExtent: tileHeight,
                       childCrossAxisExtent: tileWidth,
                       reverseCrossAxis: AxisUtils.axisDirectionIsReversed(constraints.crossAxisDirection)
                       ));
        }
示例#10
0
        public static AxisDirection?getDefaultCrossAxisDirection(BuildContext context, AxisDirection?axisDirection)
        {
            D.assert(axisDirection != null);
            switch (axisDirection)
            {
            case AxisDirection.up:
                return(AxisUtils.textDirectionToAxisDirection(Directionality.of(context)));

            case AxisDirection.right:
                return(AxisDirection.down);

            case AxisDirection.down:
                return(AxisUtils.textDirectionToAxisDirection(Directionality.of(context)));

            case AxisDirection.left:
                return(AxisDirection.down);
            }
            return(null);
        }
示例#11
0
        private List <Point> AxisSpecificAction(Point anchorPos, Point targetPos)
        {
            var foundItems = new List <Point>();

            AxisUtils.DoForBothAxes((Axis axis) =>
            {
                if (anchorPos.OppositeAxisValue(axis) == targetPos.OppositeAxisValue(axis))
                {
                    int difference           = anchorPos.AxisValue(axis) - targetPos.AxisValue(axis);
                    int normalizedDifference = Math.Sign(difference);
                    for (int i = targetPos.AxisValue(axis); i != targetPos.AxisValue(axis) + difference; i += normalizedDifference)
                    {
                        var z = i + normalizedDifference;
                        foundItems.Add(AxisUtils.CreatePoint(z, targetPos.OppositeAxisValue(axis), axis));
                    }
                }
            });

            return(foundItems);
        }
示例#12
0
        public static AxisDirection getDefaultCrossAxisDirection(BuildContext context, AxisDirection axisDirection)
        {
            switch (axisDirection)
            {
            case AxisDirection.up:
                return(AxisUtils.textDirectionToAxisDirection(Directionality.of(context)));

            case AxisDirection.right:
                return(AxisDirection.down);

            case AxisDirection.down:
                return(AxisUtils.textDirectionToAxisDirection(Directionality.of(context)));

            case AxisDirection.left:
                return(AxisDirection.down);
            }


            throw new Exception("unknown axisDirection");
        }
示例#13
0
        public override bool debugAssertIsValid(
            bool isAppliedConstraint = false,
            InformationCollector informationCollector = null
            )
        {
            D.assert(() => {
                var verify = new Action <bool, string>((bool check, string message) => {
                    if (check)
                    {
                        return;
                    }

                    var information = new StringBuilder();
                    if (informationCollector != null)
                    {
                        informationCollector(information);
                    }

                    throw new UIWidgetsError(
                        $"{this.GetType()} is not valid: {message}\n{information}The offending constraints were: \n  {this}");
                });

                verify(this.scrollOffset >= 0.0f, "The \"scrollOffset\" is negative.");
                verify(this.crossAxisExtent >= 0.0f, "The \"crossAxisExtent\" is negative.");
                verify(
                    AxisUtils.axisDirectionToAxis(this.axisDirection) !=
                    AxisUtils.axisDirectionToAxis(this.crossAxisDirection),
                    "The \"axisDirection\" and the \"crossAxisDirection\" are along the same axis.");
                verify(this.viewportMainAxisExtent >= 0.0f, "The \"viewportMainAxisExtent\" is negative.");
                verify(this.remainingPaintExtent >= 0.0f, "The \"remainingPaintExtent\" is negative.");
                verify(this.remainingCacheExtent >= 0.0f, "The \"remainingCacheExtent\" is negative.");
                verify(this.cacheOrigin <= 0.0f, "The \"cacheOrigin\" is positive.");
                verify(this.isNormalized, "The constraints are not normalized.");
                return(true);
            });

            return(true);
        }
示例#14
0
        public override bool debugAssertIsValid(
            bool isAppliedConstraint = false,
            InformationCollector informationCollector = null
            )
        {
            D.assert(() => {
                bool hasErrors             = false;
                StringBuilder errorMessage = new StringBuilder("\n");
                var verify = new Action <bool, string>((bool check, string message) => {
                    if (check)
                    {
                        return;
                    }
                    hasErrors = true;
                    errorMessage.AppendLine($"  {message}");
                });
                void verifyFloat(float?property, string name, bool mustBePositive = false, bool mustBeNegative = false)
                {
                    verify(property != null, $"The \"{name}\" is null.");
                    if (property.Value.isNaN())
                    {
                        string additional = ".";
                        if (mustBePositive)
                        {
                            additional = ", expected greater than or equal to zero.";
                        }
                        else if (mustBeNegative)
                        {
                            additional = ", expected less than or equal to zero.";
                        }
                        verify(false, $"The \"{name}\" is NaN" + $"{additional}");
                    }
                    else if (mustBePositive)
                    {
                        verify(property >= 0.0f, $"The \"{name}\" is negative.");
                    }
                    else if (mustBeNegative)
                    {
                        verify(property <= 0.0f, $"The \"{name}\" is positive.");
                    }
                }
                verify(axis != null, "The \"axis\" is null.");
                verify(growthDirection != null, "The \"growthDirection\" is null.");
                verifyFloat(scrollOffset, "scrollOffset");
                verifyFloat(overlap, "overlap");
                verifyFloat(crossAxisExtent, "crossAxisExtent");
                verifyFloat(scrollOffset, "scrollOffset", mustBePositive: true);
                verify(crossAxisDirection != null, "The \"crossAxisDirection\" is null.");
                verify(AxisUtils.axisDirectionToAxis(axisDirection) != AxisUtils.axisDirectionToAxis(crossAxisDirection), "The \"axisDirection\" and the \"crossAxisDirection\" are along the same axis.");
                verifyFloat(viewportMainAxisExtent, "viewportMainAxisExtent", mustBePositive: true);
                verifyFloat(remainingPaintExtent, "remainingPaintExtent", mustBePositive: true);
                verifyFloat(remainingCacheExtent, "remainingCacheExtent", mustBePositive: true);
                verifyFloat(cacheOrigin, "cacheOrigin", mustBeNegative: true);
                verifyFloat(precedingScrollExtent, "precedingScrollExtent", mustBePositive: true);
                verify(isNormalized, "The constraints are not normalized."); // should be redundant with earlier checks


                if (hasErrors)
                {
                    List <DiagnosticsNode> diagnosticInfo = new List <DiagnosticsNode>();
                    diagnosticInfo.Add(new ErrorSummary($"{GetType()} is not valid: {errorMessage}"));
                    if (informationCollector != null)
                    {
                        diagnosticInfo.AddRange(informationCollector.Invoke());
                    }
                    diagnosticInfo.Add(new DiagnosticsProperty <SliverConstraints>("The offending constraints were", this, style: DiagnosticsTreeStyle.errorProperty));

                    throw new UIWidgetsError(diagnosticInfo);
                }
                return(true);
            });

            return(true);
        }
示例#15
0
 public static Axis?axis(this ScrollMetrics it)
 {
     return(AxisUtils.axisDirectionToAxis(axisDirection: it.axisDirection));
 }
示例#16
0
        protected override void performLayout()
        {
            D.assert(_debugHasNecessaryDirections);
            BoxConstraints constraints   = this.constraints;
            int            totalFlex     = 0;
            int            totalChildren = 0;

            D.assert(constraints != null);
            float maxMainSize = _direction == Axis.horizontal
                ? constraints.maxWidth
                : constraints.maxHeight;
            bool canFlex = maxMainSize < float.PositiveInfinity;

            float     crossSize     = 0.0f;
            float     allocatedSize = 0.0f;
            RenderBox child         = firstChild;
            RenderBox lastFlexChild = null;

            while (child != null)
            {
                var childParentData = (FlexParentData)child.parentData;
                totalChildren++;
                int flex = _getFlex(child);
                if (flex > 0)
                {
                    totalFlex    += childParentData.flex;
                    lastFlexChild = child;
                }
                else
                {
                    BoxConstraints innerConstraints = null;
                    if (crossAxisAlignment == CrossAxisAlignment.stretch)
                    {
                        switch (_direction)
                        {
                        case Axis.horizontal:
                            innerConstraints = new BoxConstraints(
                                minHeight: constraints.maxHeight,
                                maxHeight: constraints.maxHeight);
                            break;

                        case Axis.vertical:
                            innerConstraints = new BoxConstraints(
                                minWidth: constraints.maxWidth,
                                maxWidth: constraints.maxWidth);
                            break;
                        }
                    }
                    else
                    {
                        switch (_direction)
                        {
                        case Axis.horizontal:
                            innerConstraints = new BoxConstraints(
                                maxHeight: constraints.maxHeight);
                            break;

                        case Axis.vertical:
                            innerConstraints = new BoxConstraints(
                                maxWidth: constraints.maxWidth);
                            break;
                        }
                    }

                    child.layout(innerConstraints, parentUsesSize: true);
                    allocatedSize += _getMainSize(child);
                    crossSize      = Mathf.Max(crossSize, _getCrossSize(child));
                }
                D.assert(child.parentData == childParentData);
                child = childParentData.nextSibling;
            }

            float freeSpace           = Mathf.Max(0.0f, (canFlex ? maxMainSize : 0.0f) - allocatedSize);
            float allocatedFlexSpace  = 0.0f;
            float maxBaselineDistance = 0.0f;

            if (totalFlex > 0 || crossAxisAlignment == CrossAxisAlignment.baseline)
            {
                float spacePerFlex = canFlex && totalFlex > 0 ? (freeSpace / totalFlex) : float.NaN;
                child = firstChild;
                float maxSizeAboveBaseline = 0;
                float maxSizeBelowBaseline = 0;
                while (child != null)
                {
                    int flex = _getFlex(child);
                    if (flex > 0)
                    {
                        float maxChildExtent = canFlex
                            ? (child == lastFlexChild ? (freeSpace - allocatedFlexSpace) : spacePerFlex * flex)
                            : float.PositiveInfinity;
                        float minChildExtent = 0.0f;
                        switch (_getFit(child))
                        {
                        case FlexFit.tight:
                            minChildExtent = maxChildExtent;
                            break;

                        case FlexFit.loose:
                            minChildExtent = 0.0f;
                            break;
                        }

                        BoxConstraints innerConstraints = null;
                        if (crossAxisAlignment == CrossAxisAlignment.stretch)
                        {
                            switch (_direction)
                            {
                            case Axis.horizontal:
                                innerConstraints = new BoxConstraints(
                                    minWidth: minChildExtent,
                                    maxWidth: maxChildExtent,
                                    minHeight: constraints.maxHeight,
                                    maxHeight: constraints.maxHeight);
                                break;

                            case Axis.vertical:
                                innerConstraints = new BoxConstraints(
                                    minWidth: constraints.maxWidth,
                                    maxWidth: constraints.maxWidth,
                                    minHeight: minChildExtent,
                                    maxHeight: maxChildExtent);
                                break;
                            }
                        }
                        else
                        {
                            switch (_direction)
                            {
                            case Axis.horizontal:
                                innerConstraints = new BoxConstraints(
                                    minWidth: minChildExtent,
                                    maxWidth: maxChildExtent,
                                    maxHeight: constraints.maxHeight);
                                break;

                            case Axis.vertical:
                                innerConstraints = new BoxConstraints(
                                    maxWidth: constraints.maxWidth,
                                    minHeight: minChildExtent,
                                    maxHeight: maxChildExtent);
                                break;
                            }
                        }

                        child.layout(innerConstraints, parentUsesSize: true);
                        float childSize = _getMainSize(child);
                        allocatedSize      += childSize;
                        allocatedFlexSpace += maxChildExtent;
                        crossSize           = Mathf.Max(crossSize, _getCrossSize(child));
                    }

                    if (crossAxisAlignment == CrossAxisAlignment.baseline)
                    {
                        float?distance = child.getDistanceToBaseline(textBaseline, onlyReal: true);
                        if (distance != null)
                        {
                            maxBaselineDistance  = Mathf.Max(maxBaselineDistance, distance.Value);
                            maxSizeAboveBaseline = Mathf.Max(distance.Value, maxSizeAboveBaseline);
                            maxSizeBelowBaseline = Mathf.Max(child.size.height - distance.Value, maxSizeBelowBaseline);
                            crossSize            = maxSizeAboveBaseline + maxSizeBelowBaseline;
                        }
                    }

                    var childParentData = (FlexParentData)child.parentData;
                    child = childParentData.nextSibling;
                }
            }

            float idealSize       = canFlex && mainAxisSize == MainAxisSize.max ? maxMainSize : allocatedSize;
            float actualSize      = 0.0f;
            float actualSizeDelta = 0.0f;

            switch (_direction)
            {
            case Axis.horizontal:
                size       = constraints.constrain(new Size(idealSize, crossSize));
                actualSize = size.width;
                crossSize  = size.height;
                break;

            case Axis.vertical:
                size       = constraints.constrain(new Size(crossSize, idealSize));
                actualSize = size.height;
                crossSize  = size.width;
                break;
            }

            actualSizeDelta = actualSize - allocatedSize;
            _overflow       = Mathf.Max(0.0f, -actualSizeDelta);

            float remainingSpace = Mathf.Max(0.0f, actualSizeDelta);
            float leadingSpace   = 0.0f;
            float betweenSpace   = 0.0f;
            bool  flipMainAxis   = !_startIsTopLeft(direction, textDirection, verticalDirection);

            switch (_mainAxisAlignment)
            {
            case MainAxisAlignment.start:
                leadingSpace = 0.0f;
                betweenSpace = 0.0f;
                break;

            case MainAxisAlignment.end:
                leadingSpace = remainingSpace;
                betweenSpace = 0.0f;
                break;

            case MainAxisAlignment.center:
                leadingSpace = remainingSpace / 2.0f;
                betweenSpace = 0.0f;
                break;

            case MainAxisAlignment.spaceBetween:
                leadingSpace = 0.0f;
                betweenSpace = totalChildren > 1 ? remainingSpace / (totalChildren - 1) : 0.0f;
                break;

            case MainAxisAlignment.spaceAround:
                betweenSpace = totalChildren > 0 ? remainingSpace / totalChildren : 0.0f;
                leadingSpace = betweenSpace / 2.0f;
                break;

            case MainAxisAlignment.spaceEvenly:
                betweenSpace = totalChildren > 0 ? remainingSpace / (totalChildren + 1) : 0.0f;
                leadingSpace = betweenSpace;
                break;
            }

            // Position elements
            float childMainPosition = flipMainAxis ? actualSize - leadingSpace : leadingSpace;

            child = firstChild;
            while (child != null)
            {
                var   childParentData    = (FlexParentData)child.parentData;
                float childCrossPosition = 0.0f;
                switch (_crossAxisAlignment)
                {
                case CrossAxisAlignment.start:
                case CrossAxisAlignment.end:
                    childCrossPosition =
                        _startIsTopLeft(
                            AxisUtils.flipAxis(direction), textDirection, verticalDirection)
                        == (_crossAxisAlignment == CrossAxisAlignment.start)
                                ? 0.0f
                                : crossSize - _getCrossSize(child);
                    break;

                case CrossAxisAlignment.center:
                    childCrossPosition = crossSize / 2.0f - _getCrossSize(child) / 2.0f;
                    break;

                case CrossAxisAlignment.stretch:
                    childCrossPosition = 0.0f;
                    break;

                case CrossAxisAlignment.baseline:
                    childCrossPosition = 0.0f;
                    if (_direction == Axis.horizontal)
                    {
                        float?distance = child.getDistanceToBaseline(textBaseline, onlyReal: true);
                        if (distance != null)
                        {
                            childCrossPosition = maxBaselineDistance - distance.Value;
                        }
                    }

                    break;
                }

                if (flipMainAxis)
                {
                    childMainPosition -= _getMainSize(child);
                }

                switch (_direction)
                {
                case Axis.horizontal:
                    childParentData.offset = new Offset(childMainPosition, childCrossPosition);
                    break;

                case Axis.vertical:
                    childParentData.offset = new Offset(childCrossPosition, childMainPosition);
                    break;
                }

                if (flipMainAxis)
                {
                    childMainPosition -= betweenSpace;
                }
                else
                {
                    childMainPosition += _getMainSize(child) + betweenSpace;
                }

                child = childParentData.nextSibling;
            }
        }
示例#17
0
        protected override void performLayout()
        {
            int    totalFlex     = 0;
            int    totalChildren = 0;
            double maxMainSize   = this._direction == Axis.horizontal
                ? this.constraints.maxWidth
                : this.constraints.maxHeight;
            bool canFlex = maxMainSize < double.PositiveInfinity;

            double    crossSize     = 0.0;
            double    allocatedSize = 0.0;
            RenderBox child         = this.firstChild;
            RenderBox lastFlexChild = null;

            while (child != null)
            {
                var childParentData = (FlexParentData)child.parentData;
                totalChildren++;
                int flex = this._getFlex(child);
                if (flex > 0)
                {
                    totalFlex    += childParentData.flex;
                    lastFlexChild = child;
                }
                else
                {
                    BoxConstraints innerConstraints = null;
                    if (this.crossAxisAlignment == CrossAxisAlignment.stretch)
                    {
                        switch (this._direction)
                        {
                        case Axis.horizontal:
                            innerConstraints = new BoxConstraints(
                                minHeight: this.constraints.maxHeight,
                                maxHeight: this.constraints.maxHeight);
                            break;

                        case Axis.vertical:
                            innerConstraints = new BoxConstraints(
                                minWidth: this.constraints.maxWidth,
                                maxWidth: this.constraints.maxWidth);
                            break;
                        }
                    }
                    else
                    {
                        switch (this._direction)
                        {
                        case Axis.horizontal:
                            innerConstraints = new BoxConstraints(
                                maxHeight: this.constraints.maxHeight);
                            break;

                        case Axis.vertical:
                            innerConstraints = new BoxConstraints(
                                maxWidth: this.constraints.maxWidth);
                            break;
                        }
                    }

                    child.layout(innerConstraints, parentUsesSize: true);
                    allocatedSize += this._getMainSize(child);
                    crossSize      = Math.Max(crossSize, this._getCrossSize(child));
                }

                child = childParentData.nextSibling;
            }

            double freeSpace           = Math.Max(0.0, (canFlex ? maxMainSize : 0.0) - allocatedSize);
            double allocatedFlexSpace  = 0.0;
            double maxBaselineDistance = 0.0;

            if (totalFlex > 0 || this.crossAxisAlignment == CrossAxisAlignment.baseline)
            {
                double spacePerFlex = canFlex && totalFlex > 0 ? (freeSpace / totalFlex) : double.NaN;
                child = this.firstChild;
                while (child != null)
                {
                    int flex = this._getFlex(child);
                    if (flex > 0)
                    {
                        double maxChildExtent = canFlex
                            ? (child == lastFlexChild ? (freeSpace - allocatedFlexSpace) : spacePerFlex * flex)
                            : double.PositiveInfinity;
                        double minChildExtent = 0.0;
                        switch (this._getFit(child))
                        {
                        case FlexFit.tight:
                            minChildExtent = maxChildExtent;
                            break;

                        case FlexFit.loose:
                            minChildExtent = 0.0;
                            break;
                        }

                        BoxConstraints innerConstraints = null;
                        if (this.crossAxisAlignment == CrossAxisAlignment.stretch)
                        {
                            switch (this._direction)
                            {
                            case Axis.horizontal:
                                innerConstraints = new BoxConstraints(
                                    minWidth: minChildExtent,
                                    maxWidth: maxChildExtent,
                                    minHeight: this.constraints.maxHeight,
                                    maxHeight: this.constraints.maxHeight);
                                break;

                            case Axis.vertical:
                                innerConstraints = new BoxConstraints(
                                    minWidth: this.constraints.maxWidth,
                                    maxWidth: this.constraints.maxWidth,
                                    minHeight: minChildExtent,
                                    maxHeight: maxChildExtent);
                                break;
                            }
                        }
                        else
                        {
                            switch (this._direction)
                            {
                            case Axis.horizontal:
                                innerConstraints = new BoxConstraints(
                                    minWidth: minChildExtent,
                                    maxWidth: maxChildExtent,
                                    maxHeight: this.constraints.maxHeight);
                                break;

                            case Axis.vertical:
                                innerConstraints = new BoxConstraints(
                                    maxWidth: this.constraints.maxWidth,
                                    minHeight: minChildExtent,
                                    maxHeight: maxChildExtent);
                                break;
                            }
                        }

                        child.layout(innerConstraints, parentUsesSize: true);
                        double childSize = this._getMainSize(child);
                        allocatedSize      += childSize;
                        allocatedFlexSpace += maxChildExtent;
                        crossSize           = Math.Max(crossSize, this._getCrossSize(child));
                    }

                    if (this.crossAxisAlignment == CrossAxisAlignment.baseline)
                    {
                        double?distance = child.getDistanceToBaseline(this.textBaseline, onlyReal: true);
                        if (distance != null)
                        {
                            maxBaselineDistance = Math.Max(maxBaselineDistance, distance.Value);
                        }
                    }

                    var childParentData = (FlexParentData)child.parentData;
                    child = childParentData.nextSibling;
                }
            }

            double idealSize       = canFlex && this.mainAxisSize == MainAxisSize.max ? maxMainSize : allocatedSize;
            double actualSize      = 0.0;
            double actualSizeDelta = 0.0;

            switch (this._direction)
            {
            case Axis.horizontal:
                this.size  = this.constraints.constrain(new Size(idealSize, crossSize));
                actualSize = this.size.width;
                crossSize  = this.size.height;
                break;

            case Axis.vertical:
                this.size  = this.constraints.constrain(new Size(crossSize, idealSize));
                actualSize = this.size.height;
                crossSize  = this.size.width;
                break;
            }

            actualSizeDelta = actualSize - allocatedSize;
            this._overflow  = Math.Max(0.0, -actualSizeDelta);

            double remainingSpace = Math.Max(0.0, actualSizeDelta);
            double leadingSpace   = 0.0;
            double betweenSpace   = 0.0;
            bool   flipMainAxis   = !_startIsTopLeft(this.direction, this.textDirection, this.verticalDirection);

            switch (this._mainAxisAlignment)
            {
            case MainAxisAlignment.start:
                leadingSpace = 0.0;
                betweenSpace = 0.0;
                break;

            case MainAxisAlignment.end:
                leadingSpace = remainingSpace;
                betweenSpace = 0.0;
                break;

            case MainAxisAlignment.center:
                leadingSpace = remainingSpace / 2.0;
                betweenSpace = 0.0;
                break;

            case MainAxisAlignment.spaceBetween:
                leadingSpace = 0.0;
                betweenSpace = totalChildren > 1 ? remainingSpace / (totalChildren - 1) : 0.0;
                break;

            case MainAxisAlignment.spaceAround:
                betweenSpace = totalChildren > 0 ? remainingSpace / totalChildren : 0.0;
                leadingSpace = betweenSpace / 2.0;
                break;

            case MainAxisAlignment.spaceEvenly:
                betweenSpace = totalChildren > 0 ? remainingSpace / (totalChildren + 1) : 0.0;
                leadingSpace = betweenSpace;
                break;
            }

            // Position elements
            double childMainPosition = flipMainAxis ? actualSize - leadingSpace : leadingSpace;

            child = this.firstChild;
            while (child != null)
            {
                var    childParentData    = (FlexParentData)child.parentData;
                double childCrossPosition = 0.0;
                switch (this._crossAxisAlignment)
                {
                case CrossAxisAlignment.start:
                case CrossAxisAlignment.end:
                    childCrossPosition =
                        _startIsTopLeft(
                            AxisUtils.flipAxis(this.direction), this.textDirection, this.verticalDirection)
                        == (this._crossAxisAlignment == CrossAxisAlignment.start)
                                ? 0.0
                                : crossSize - this._getCrossSize(child);
                    break;

                case CrossAxisAlignment.center:
                    childCrossPosition = crossSize / 2.0 - this._getCrossSize(child) / 2.0;
                    break;

                case CrossAxisAlignment.stretch:
                    childCrossPosition = 0.0;
                    break;

                case CrossAxisAlignment.baseline:
                    childCrossPosition = 0.0;
                    if (this._direction == Axis.horizontal)
                    {
                        double?distance = child.getDistanceToBaseline(this.textBaseline, onlyReal: true);
                        if (distance != null)
                        {
                            childCrossPosition = maxBaselineDistance - distance.Value;
                        }
                    }

                    break;
                }

                if (flipMainAxis)
                {
                    childMainPosition -= this._getMainSize(child);
                }

                switch (this._direction)
                {
                case Axis.horizontal:
                    childParentData.offset = new Offset(childMainPosition, childCrossPosition);
                    break;

                case Axis.vertical:
                    childParentData.offset = new Offset(childCrossPosition, childMainPosition);
                    break;
                }

                if (flipMainAxis)
                {
                    childMainPosition -= betweenSpace;
                }
                else
                {
                    childMainPosition += this._getMainSize(child) + betweenSpace;
                }

                child = childParentData.nextSibling;
            }
        }