Beispiel #1
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;
            }
        }
Beispiel #2
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;
            }
        }