mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-01 04:08:07 +00:00
Add baseline support to ASStackLayoutSpec
This commit is contained in:
parent
80bbf79046
commit
f289b3345a
@ -48,6 +48,8 @@
|
|||||||
@synthesize flexBasis = _flexBasis;
|
@synthesize flexBasis = _flexBasis;
|
||||||
@synthesize alignSelf = _alignSelf;
|
@synthesize alignSelf = _alignSelf;
|
||||||
@synthesize preferredFrameSize = _preferredFrameSize;
|
@synthesize preferredFrameSize = _preferredFrameSize;
|
||||||
|
@synthesize ascender = _ascender;
|
||||||
|
@synthesize descender = _descender;
|
||||||
|
|
||||||
BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector)
|
BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector)
|
||||||
{
|
{
|
||||||
@ -157,6 +159,8 @@ void ASDisplayNodeRespectThreadAffinityOfNode(ASDisplayNode *node, void (^block)
|
|||||||
|
|
||||||
_flexBasis = ASRelativeDimensionUnconstrained;
|
_flexBasis = ASRelativeDimensionUnconstrained;
|
||||||
_preferredFrameSize = CGSizeZero;
|
_preferredFrameSize = CGSizeZero;
|
||||||
|
_ascender = 0;
|
||||||
|
_descender = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)init
|
- (id)init
|
||||||
|
|||||||
@ -355,6 +355,9 @@ ASDISPLAYNODE_INLINE CGFloat ceilPixelValue(CGFloat f)
|
|||||||
self.isAccessibilityElement = YES;
|
self.isAccessibilityElement = YES;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.ascender = [[attributedString attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender];
|
||||||
|
self.descender = [[attributedString attribute:NSFontAttributeName atIndex:attributedString.length - 1 effectiveRange:NULL] descender];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Text Layout
|
#pragma mark - Text Layout
|
||||||
|
|||||||
@ -24,6 +24,8 @@
|
|||||||
@synthesize flexShrink = _flexShrink;
|
@synthesize flexShrink = _flexShrink;
|
||||||
@synthesize flexBasis = _flexBasis;
|
@synthesize flexBasis = _flexBasis;
|
||||||
@synthesize alignSelf = _alignSelf;
|
@synthesize alignSelf = _alignSelf;
|
||||||
|
@synthesize ascender = _ascender;
|
||||||
|
@synthesize descender = _descender;
|
||||||
|
|
||||||
+ (instancetype)new
|
+ (instancetype)new
|
||||||
{
|
{
|
||||||
|
|||||||
@ -57,6 +57,16 @@
|
|||||||
*/
|
*/
|
||||||
@property (nonatomic, readwrite) ASStackLayoutAlignSelf alignSelf;
|
@property (nonatomic, readwrite) ASStackLayoutAlignSelf alignSelf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Used for baseline alignment. The distance from the top of the object to its baseline.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readwrite) CGFloat ascender;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Used for baseline alignment. The distance from the baseline of the object to its bottom.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readwrite) CGFloat descender;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract Calculate a layout based on given size range.
|
* @abstract Calculate a layout based on given size range.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -23,4 +23,8 @@ typedef NS_ENUM(NSUInteger, ASStackLayoutAlignSelf) {
|
|||||||
ASStackLayoutAlignSelfCenter,
|
ASStackLayoutAlignSelfCenter,
|
||||||
/** Expand to fill cross axis */
|
/** Expand to fill cross axis */
|
||||||
ASStackLayoutAlignSelfStretch,
|
ASStackLayoutAlignSelfStretch,
|
||||||
|
/** Children align to their first baseline. Only available for horizontal stack nodes */
|
||||||
|
ASStackLayoutAlignSelfBaselineFirst,
|
||||||
|
/** Children align to their last baseline. Only available for horizontal stack nodes */
|
||||||
|
ASStackLayoutAlignSelfBaselineLast,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -47,6 +47,10 @@ typedef NS_ENUM(NSUInteger, ASStackLayoutAlignItems) {
|
|||||||
ASStackLayoutAlignItemsCenter,
|
ASStackLayoutAlignItemsCenter,
|
||||||
/** Expand children to fill cross axis */
|
/** Expand children to fill cross axis */
|
||||||
ASStackLayoutAlignItemsStretch,
|
ASStackLayoutAlignItemsStretch,
|
||||||
|
/** Children align to their first baseline. Only available for horizontal stack nodes */
|
||||||
|
ASStackLayoutAlignItemsBaselineFirst,
|
||||||
|
/** Children align to their last baseline. Only available for horizontal stack nodes */
|
||||||
|
ASStackLayoutAlignItemsBaselineLast,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@ -55,6 +55,10 @@ inline ASStackLayoutAlignItems alignment(ASStackLayoutAlignSelf childAlignment,
|
|||||||
return ASStackLayoutAlignItemsStart;
|
return ASStackLayoutAlignItemsStart;
|
||||||
case ASStackLayoutAlignSelfStretch:
|
case ASStackLayoutAlignSelfStretch:
|
||||||
return ASStackLayoutAlignItemsStretch;
|
return ASStackLayoutAlignItemsStretch;
|
||||||
|
case ASStackLayoutAlignSelfBaselineFirst:
|
||||||
|
return ASStackLayoutAlignItemsBaselineFirst;
|
||||||
|
case ASStackLayoutAlignSelfBaselineLast:
|
||||||
|
return ASStackLayoutAlignItemsBaselineLast;
|
||||||
case ASStackLayoutAlignSelfAuto:
|
case ASStackLayoutAlignSelfAuto:
|
||||||
default:
|
default:
|
||||||
return stackAlignment;
|
return stackAlignment;
|
||||||
|
|||||||
@ -15,9 +15,21 @@
|
|||||||
#import "ASStackLayoutSpecUtilities.h"
|
#import "ASStackLayoutSpecUtilities.h"
|
||||||
#import "ASLayoutable.h"
|
#import "ASLayoutable.h"
|
||||||
|
|
||||||
|
static CGFloat baselineForItem(const ASStackLayoutSpecStyle &style,
|
||||||
|
const ASStackUnpositionedItem &item) {
|
||||||
|
const ASStackLayoutAlignItems alignItems = alignment(item.child.alignSelf, style.alignItems);
|
||||||
|
if (alignItems == ASStackLayoutAlignItemsBaselineFirst) {
|
||||||
|
return item.child.ascender;
|
||||||
|
} else if (alignItems == ASStackLayoutAlignItemsBaselineLast) {
|
||||||
|
return item.layout.size.height + item.child.descender;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static CGFloat crossOffset(const ASStackLayoutSpecStyle &style,
|
static CGFloat crossOffset(const ASStackLayoutSpecStyle &style,
|
||||||
const ASStackUnpositionedItem &l,
|
const ASStackUnpositionedItem &l,
|
||||||
const CGFloat crossSize)
|
const CGFloat crossSize,
|
||||||
|
const CGFloat maxBaseline)
|
||||||
{
|
{
|
||||||
switch (alignment(l.child.alignSelf, style.alignItems)) {
|
switch (alignment(l.child.alignSelf, style.alignItems)) {
|
||||||
case ASStackLayoutAlignItemsEnd:
|
case ASStackLayoutAlignItemsEnd:
|
||||||
@ -27,9 +39,14 @@ static CGFloat crossOffset(const ASStackLayoutSpecStyle &style,
|
|||||||
case ASStackLayoutAlignItemsStart:
|
case ASStackLayoutAlignItemsStart:
|
||||||
case ASStackLayoutAlignItemsStretch:
|
case ASStackLayoutAlignItemsStretch:
|
||||||
return 0;
|
return 0;
|
||||||
|
case ASStackLayoutAlignItemsBaselineFirst:
|
||||||
|
return maxBaseline - l.child.ascender;
|
||||||
|
case ASStackLayoutAlignItemsBaselineLast:
|
||||||
|
return maxBaseline - baselineForItem(style, l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ASStackPositionedLayout stackedLayout(const ASStackLayoutSpecStyle &style,
|
static ASStackPositionedLayout stackedLayout(const ASStackLayoutSpecStyle &style,
|
||||||
const CGFloat offset,
|
const CGFloat offset,
|
||||||
const ASStackUnpositionedLayout &unpositionedLayout,
|
const ASStackUnpositionedLayout &unpositionedLayout,
|
||||||
@ -44,6 +61,12 @@ static ASStackPositionedLayout stackedLayout(const ASStackLayoutSpecStyle &style
|
|||||||
const auto minCrossSize = crossDimension(style.direction, constrainedSize.min);
|
const auto minCrossSize = crossDimension(style.direction, constrainedSize.min);
|
||||||
const auto maxCrossSize = crossDimension(style.direction, constrainedSize.max);
|
const auto maxCrossSize = crossDimension(style.direction, constrainedSize.max);
|
||||||
const CGFloat crossSize = MIN(MAX(minCrossSize, largestChildCrossSize), maxCrossSize);
|
const CGFloat crossSize = MIN(MAX(minCrossSize, largestChildCrossSize), maxCrossSize);
|
||||||
|
|
||||||
|
// Find the maximum height for the baseline
|
||||||
|
const auto baselineIt = std::max_element(unpositionedLayout.items.begin(), unpositionedLayout.items.end(), [&](const ASStackUnpositionedItem &a, const ASStackUnpositionedItem &b){
|
||||||
|
return baselineForItem(style, a) < baselineForItem(style, b);
|
||||||
|
});
|
||||||
|
const CGFloat maxBaseLine = baselineIt == unpositionedLayout.items.end() ? 0 : baselineForItem(style, *baselineIt);
|
||||||
|
|
||||||
CGPoint p = directionPoint(style.direction, offset, 0);
|
CGPoint p = directionPoint(style.direction, offset, 0);
|
||||||
BOOL first = YES;
|
BOOL first = YES;
|
||||||
@ -53,7 +76,7 @@ static ASStackPositionedLayout stackedLayout(const ASStackLayoutSpecStyle &style
|
|||||||
p = p + directionPoint(style.direction, style.spacing, 0);
|
p = p + directionPoint(style.direction, style.spacing, 0);
|
||||||
}
|
}
|
||||||
first = NO;
|
first = NO;
|
||||||
l.layout.position = p + directionPoint(style.direction, 0, crossOffset(style, l, crossSize));
|
l.layout.position = p + directionPoint(style.direction, 0, crossOffset(style, l, crossSize, maxBaseLine));
|
||||||
p = p + directionPoint(style.direction, stackDimension(style.direction, l.layout.size) + l.child.spacingAfter, 0);
|
p = p + directionPoint(style.direction, stackDimension(style.direction, l.layout.size) + l.child.spacingAfter, 0);
|
||||||
return l.layout;
|
return l.layout;
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user