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; } }
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; } }