mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Implement "space between" and "space around" options of stack layout justify content
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#import "ASStackLayoutSpecUtilities.h"
|
||||
#import "ASLayoutable.h"
|
||||
#import "ASLayoutOptions.h"
|
||||
#import "ASAssert.h"
|
||||
|
||||
static CGFloat crossOffset(const ASStackLayoutSpecStyle &style,
|
||||
const ASStackUnpositionedItem &l,
|
||||
@@ -33,8 +34,20 @@ static CGFloat crossOffset(const ASStackLayoutSpecStyle &style,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Positions children according to the stack style and positioning properties.
|
||||
*
|
||||
* @param style The layout style of the overall stack layout
|
||||
* @param firstChildOffset Offset of the first child
|
||||
* @param extraSpacing Spacing between children, in addition to spacing set to the stack's layout style
|
||||
* @param lastChildOffset Offset of the last child
|
||||
* @param unpositionedLayout Unpositioned children of the stack
|
||||
* @param constrainedSize Constrained size of the stack
|
||||
*/
|
||||
static ASStackPositionedLayout stackedLayout(const ASStackLayoutSpecStyle &style,
|
||||
const CGFloat offset,
|
||||
const CGFloat firstChildOffset,
|
||||
const CGFloat extraSpacing,
|
||||
const CGFloat lastChildOffset,
|
||||
const ASStackUnpositionedLayout &unpositionedLayout,
|
||||
const ASSizeRange &constrainedSize)
|
||||
{
|
||||
@@ -48,12 +61,16 @@ static ASStackPositionedLayout stackedLayout(const ASStackLayoutSpecStyle &style
|
||||
const auto maxCrossSize = crossDimension(style.direction, constrainedSize.max);
|
||||
const CGFloat crossSize = MIN(MAX(minCrossSize, largestChildCrossSize), maxCrossSize);
|
||||
|
||||
CGPoint p = directionPoint(style.direction, offset, 0);
|
||||
CGPoint p = directionPoint(style.direction, firstChildOffset, 0);
|
||||
BOOL first = YES;
|
||||
const auto lastChild = unpositionedLayout.items.back().child;
|
||||
CGFloat offset = 0;
|
||||
|
||||
auto stackedChildren = AS::map(unpositionedLayout.items, [&](const ASStackUnpositionedItem &l) -> ASLayout *{
|
||||
p = p + directionPoint(style.direction, l.child.spacingBefore, 0);
|
||||
offset = (l.child == lastChild) ? lastChildOffset : 0;
|
||||
p = p + directionPoint(style.direction, l.child.spacingBefore + offset, 0);
|
||||
if (!first) {
|
||||
p = p + directionPoint(style.direction, style.spacing, 0);
|
||||
p = p + directionPoint(style.direction, style.spacing + extraSpacing, 0);
|
||||
}
|
||||
first = NO;
|
||||
l.layout.position = p + directionPoint(style.direction, 0, crossOffset(style, l, crossSize));
|
||||
@@ -64,16 +81,45 @@ static ASStackPositionedLayout stackedLayout(const ASStackLayoutSpecStyle &style
|
||||
return {stackedChildren, crossSize};
|
||||
}
|
||||
|
||||
static ASStackPositionedLayout stackedLayout(const ASStackLayoutSpecStyle &style,
|
||||
const CGFloat firstChildOffset,
|
||||
const ASStackUnpositionedLayout &unpositionedLayout,
|
||||
const ASSizeRange &constrainedSize)
|
||||
{
|
||||
return stackedLayout(style, firstChildOffset, 0, 0, unpositionedLayout, constrainedSize);
|
||||
}
|
||||
|
||||
ASStackPositionedLayout ASStackPositionedLayout::compute(const ASStackUnpositionedLayout &unpositionedLayout,
|
||||
const ASStackLayoutSpecStyle &style,
|
||||
const ASSizeRange &constrainedSize)
|
||||
{
|
||||
switch (style.justifyContent) {
|
||||
const auto numOfItems = unpositionedLayout.items.size();
|
||||
ASDisplayNodeCAssertTrue(numOfItems > 0);
|
||||
const CGFloat violation = unpositionedLayout.violation;
|
||||
ASStackLayoutJustifyContent justifyContent = style.justifyContent;
|
||||
|
||||
// Handle edge cases of "space between" and "space around"
|
||||
if (justifyContent == ASStackLayoutJustifyContentSpaceBetween && (violation < 0 || numOfItems == 1)) {
|
||||
justifyContent = ASStackLayoutJustifyContentStart;
|
||||
} else if (justifyContent == ASStackLayoutJustifyContentSpaceAround && (violation < 0 || numOfItems == 1)) {
|
||||
justifyContent = ASStackLayoutJustifyContentCenter;
|
||||
}
|
||||
|
||||
switch (justifyContent) {
|
||||
case ASStackLayoutJustifyContentStart:
|
||||
return stackedLayout(style, 0, unpositionedLayout, constrainedSize);
|
||||
case ASStackLayoutJustifyContentCenter:
|
||||
return stackedLayout(style, floorf(unpositionedLayout.violation / 2), unpositionedLayout, constrainedSize);
|
||||
return stackedLayout(style, floorf(violation / 2), unpositionedLayout, constrainedSize);
|
||||
case ASStackLayoutJustifyContentEnd:
|
||||
return stackedLayout(style, unpositionedLayout.violation, unpositionedLayout, constrainedSize);
|
||||
return stackedLayout(style, violation, unpositionedLayout, constrainedSize);
|
||||
case ASStackLayoutJustifyContentSpaceBetween: {
|
||||
const auto numOfSpacings = numOfItems - 1;
|
||||
return stackedLayout(style, 0, floorf(violation / numOfSpacings), fmodf(violation, numOfSpacings), unpositionedLayout, constrainedSize);
|
||||
}
|
||||
case ASStackLayoutJustifyContentSpaceAround: {
|
||||
// Spacing between items are twice the spacing on the edges
|
||||
CGFloat spacingUnit = floorf(violation / (numOfItems * 2));
|
||||
return stackedLayout(style, spacingUnit, spacingUnit * 2, 0, unpositionedLayout, constrainedSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user