mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-09 07:41:40 +00:00
Merge pull request #1735 from levi/betterFlatten3
[ASLayout] Clean up flattening process of ASLayout
This commit is contained in:
commit
c211c76c64
@ -62,7 +62,9 @@ NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp = @"AS
|
|||||||
@implementation ASDisplayNode
|
@implementation ASDisplayNode
|
||||||
|
|
||||||
// these dynamic properties all defined in ASLayoutOptionsPrivate.m
|
// these dynamic properties all defined in ASLayoutOptionsPrivate.m
|
||||||
@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender, sizeRange, layoutPosition;
|
@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis,
|
||||||
|
alignSelf, ascender, descender, sizeRange, layoutPosition, layoutableType;
|
||||||
|
|
||||||
@synthesize name = _name;
|
@synthesize name = _name;
|
||||||
@synthesize preferredFrameSize = _preferredFrameSize;
|
@synthesize preferredFrameSize = _preferredFrameSize;
|
||||||
@synthesize isFinalLayoutable = _isFinalLayoutable;
|
@synthesize isFinalLayoutable = _isFinalLayoutable;
|
||||||
@ -659,6 +661,11 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
return _layout == nil || _layout.isDirty;
|
return _layout == nil || _layout.isDirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (ASLayoutableType)layoutableType
|
||||||
|
{
|
||||||
|
return ASLayoutableTypeDisplayNode;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Layout Transition
|
#pragma mark - Layout Transition
|
||||||
|
|
||||||
- (void)transitionLayoutWithAnimation:(BOOL)animated
|
- (void)transitionLayoutWithAnimation:(BOOL)animated
|
||||||
@ -1916,13 +1923,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
|||||||
ASLayoutableValidateLayout(layout);
|
ASLayoutableValidateLayout(layout);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return [layout flattenedLayoutUsingPredicateBlock:^BOOL(ASLayout *evaluatedLayout) {
|
return [layout filteredNodeLayoutTree];
|
||||||
if (self.usesImplicitHierarchyManagement) {
|
|
||||||
return ASObjectIsEqual(layout, evaluatedLayout) == NO && [evaluatedLayout.layoutableObject isKindOfClass:[ASDisplayNode class]];
|
|
||||||
} else {
|
|
||||||
return [_subnodes containsObject:evaluatedLayout.layoutableObject];
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
} else {
|
} else {
|
||||||
// If neither -layoutSpecThatFits: nor -calculateSizeThatFits: is overridden by subclassses, preferredFrameSize should be used,
|
// If neither -layoutSpecThatFits: nor -calculateSizeThatFits: is overridden by subclassses, preferredFrameSize should be used,
|
||||||
// assume that the default implementation of -calculateSizeThatFits: returns it.
|
// assume that the default implementation of -calculateSizeThatFits: returns it.
|
||||||
@ -2415,7 +2416,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
|||||||
|
|
||||||
- (void)__layoutSublayouts
|
- (void)__layoutSublayouts
|
||||||
{
|
{
|
||||||
for (ASLayout *subnodeLayout in _layout.immediateSublayouts) {
|
for (ASLayout *subnodeLayout in _layout.sublayouts) {
|
||||||
((ASDisplayNode *)subnodeLayout.layoutableObject).frame = [subnodeLayout frame];
|
((ASDisplayNode *)subnodeLayout.layoutableObject).frame = [subnodeLayout frame];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,11 @@ extern BOOL CGPointIsNull(CGPoint point);
|
|||||||
*/
|
*/
|
||||||
@property (nonatomic, weak, readonly) id<ASLayoutable> layoutableObject;
|
@property (nonatomic, weak, readonly) id<ASLayoutable> layoutableObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of ASLayoutable that created this layout
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly) ASLayoutableType type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Size of the current layout
|
* Size of the current layout
|
||||||
*/
|
*/
|
||||||
@ -53,38 +58,39 @@ extern BOOL CGPointIsNull(CGPoint point);
|
|||||||
*/
|
*/
|
||||||
@property (nonatomic, readonly) NSArray<ASLayout *> *sublayouts;
|
@property (nonatomic, readonly) NSArray<ASLayout *> *sublayouts;
|
||||||
|
|
||||||
/**
|
|
||||||
* A list of sublayouts that were not already flattened.
|
|
||||||
*/
|
|
||||||
@property (nonatomic, readonly) NSArray<ASLayout *> *immediateSublayouts;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark the layout dirty for future regeneration.
|
* Mark the layout dirty for future regeneration.
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, getter=isDirty) BOOL dirty;
|
@property (nonatomic, getter=isDirty) BOOL dirty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A boolean describing if the current layout has been flattened.
|
* @abstract Returns a valid frame for the current layout computed with the size and position.
|
||||||
|
* @discussion Clamps the layout's origin or position to 0 if any of the calculated values are infinite.
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, readonly, getter=isFlattened) BOOL flattened;
|
@property (nonatomic, readonly) CGRect frame;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializer.
|
* Designated initializer
|
||||||
|
*/
|
||||||
|
- (instancetype)initWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
||||||
|
constrainedSizeRange:(ASSizeRange)sizeRange
|
||||||
|
size:(CGSize)size
|
||||||
|
position:(CGPoint)position
|
||||||
|
sublayouts:(NSArray *)sublayouts NS_DESIGNATED_INITIALIZER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience class initializer for layout construction.
|
||||||
*
|
*
|
||||||
* @param layoutableObject The backing ASLayoutable object.
|
* @param layoutableObject The backing ASLayoutable object.
|
||||||
*
|
* @param size The size of this layout.
|
||||||
* @param size The size of this layout.
|
* @param position The position of this layout within its parent (if available).
|
||||||
*
|
* @param sublayouts Sublayouts belong to the new layout.
|
||||||
* @param position The position of this layout within its parent (if available).
|
|
||||||
*
|
|
||||||
* @param sublayouts Sublayouts belong to the new layout.
|
|
||||||
*/
|
*/
|
||||||
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
||||||
constrainedSizeRange:(ASSizeRange)sizeRange
|
constrainedSizeRange:(ASSizeRange)sizeRange
|
||||||
size:(CGSize)size
|
size:(CGSize)size
|
||||||
position:(CGPoint)position
|
position:(CGPoint)position
|
||||||
sublayouts:(nullable NSArray<ASLayout *> *)sublayouts
|
sublayouts:(nullable NSArray<ASLayout *> *)sublayouts;
|
||||||
flattened:(BOOL)flattened;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience initializer that has CGPointNull position.
|
* Convenience initializer that has CGPointNull position.
|
||||||
@ -93,9 +99,7 @@ extern BOOL CGPointIsNull(CGPoint point);
|
|||||||
* or for creating a sublayout of which the position is yet to be determined.
|
* or for creating a sublayout of which the position is yet to be determined.
|
||||||
*
|
*
|
||||||
* @param layoutableObject The backing ASLayoutable object.
|
* @param layoutableObject The backing ASLayoutable object.
|
||||||
*
|
|
||||||
* @param size The size of this layout.
|
* @param size The size of this layout.
|
||||||
*
|
|
||||||
* @param sublayouts Sublayouts belong to the new layout.
|
* @param sublayouts Sublayouts belong to the new layout.
|
||||||
*/
|
*/
|
||||||
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
||||||
@ -109,7 +113,6 @@ extern BOOL CGPointIsNull(CGPoint point);
|
|||||||
* or a sublayout of which the position is yet to be determined.
|
* or a sublayout of which the position is yet to be determined.
|
||||||
*
|
*
|
||||||
* @param layoutableObject The backing ASLayoutable object.
|
* @param layoutableObject The backing ASLayoutable object.
|
||||||
*
|
|
||||||
* @param size The size of this layout.
|
* @param size The size of this layout.
|
||||||
*/
|
*/
|
||||||
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
||||||
@ -120,9 +123,7 @@ extern BOOL CGPointIsNull(CGPoint point);
|
|||||||
* Convenience initializer that is flattened and has CGPointNull position.
|
* Convenience initializer that is flattened and has CGPointNull position.
|
||||||
*
|
*
|
||||||
* @param layoutableObject The backing ASLayoutable object.
|
* @param layoutableObject The backing ASLayoutable object.
|
||||||
*
|
|
||||||
* @param size The size of this layout.
|
* @param size The size of this layout.
|
||||||
*
|
|
||||||
* @param sublayouts Sublayouts belong to the new layout.
|
* @param sublayouts Sublayouts belong to the new layout.
|
||||||
*/
|
*/
|
||||||
+ (instancetype)flattenedLayoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
+ (instancetype)flattenedLayoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
||||||
@ -131,22 +132,16 @@ extern BOOL CGPointIsNull(CGPoint point);
|
|||||||
sublayouts:(nullable NSArray<ASLayout *> *)sublayouts;
|
sublayouts:(nullable NSArray<ASLayout *> *)sublayouts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract Evaluates a given predicate block against each object in the receiving layout tree
|
* Convenience initializer that creates a layout based on the values of the given layout, with a new position
|
||||||
* and returns a new, 1-level deep layout containing the objects for which the predicate block returns true.
|
* @param layout The layout to use to create the new layout
|
||||||
*
|
* @param position The position of the new layout
|
||||||
* @param predicateBlock The block is applied to a layout to be evaluated.
|
|
||||||
* The block takes 1 argument: evaluatedLayout - the layout to be evaluated.
|
|
||||||
* The block returns YES if evaluatedLayout evaluates to true, otherwise NO.
|
|
||||||
*
|
|
||||||
* @return A new, 1-level deep layout containing the layouts for which the predicate block returns true.
|
|
||||||
*/
|
*/
|
||||||
- (ASLayout *)flattenedLayoutUsingPredicateBlock:(BOOL (^)(ASLayout *evaluatedLayout))predicateBlock;
|
+ (instancetype)layoutWithLayout:(ASLayout *)layout position:(CGPoint)position;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract Returns a valid frame for the current layout computed with the size and position.
|
* Traverses the existing layout tree and generates a new tree that represents only ASDisplayNode layouts
|
||||||
* @discussion Clamps the layout's origin or position to 0 if any of the calculated values are infinite.
|
|
||||||
*/
|
*/
|
||||||
- (CGRect)frame;
|
- (ASLayout *)filteredNodeLayoutTree;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@ -9,10 +9,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#import "ASLayout.h"
|
#import "ASLayout.h"
|
||||||
|
|
||||||
#import "ASAssert.h"
|
#import "ASAssert.h"
|
||||||
#import "ASLayoutSpecUtilities.h"
|
|
||||||
#import "ASInternalHelpers.h"
|
|
||||||
#import "ASDimension.h"
|
#import "ASDimension.h"
|
||||||
|
#import "ASInternalHelpers.h"
|
||||||
|
#import "ASLayoutSpecUtilities.h"
|
||||||
|
|
||||||
#import <queue>
|
#import <queue>
|
||||||
|
|
||||||
CGPoint const CGPointNull = {NAN, NAN};
|
CGPoint const CGPointNull = {NAN, NAN};
|
||||||
@ -22,25 +24,35 @@ extern BOOL CGPointIsNull(CGPoint point)
|
|||||||
return isnan(point.x) && isnan(point.y);
|
return isnan(point.x) && isnan(point.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@interface ASLayout ()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A boolean describing if the current layout has been flattened.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, getter=isFlattened) BOOL flattened;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation ASLayout
|
@implementation ASLayout
|
||||||
|
|
||||||
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
@dynamic frame, type;
|
||||||
constrainedSizeRange:(ASSizeRange)sizeRange
|
|
||||||
size:(CGSize)size
|
- (instancetype)initWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
||||||
position:(CGPoint)position
|
constrainedSizeRange:(ASSizeRange)sizeRange
|
||||||
sublayouts:(NSArray *)sublayouts
|
size:(CGSize)size
|
||||||
flattened:(BOOL)flattened
|
position:(CGPoint)position
|
||||||
|
sublayouts:(NSArray *)sublayouts
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssert(layoutableObject, @"layoutableObject is required.");
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
NSParameterAssert(layoutableObject);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
for (ASLayout *sublayout in sublayouts) {
|
for (ASLayout *sublayout in sublayouts) {
|
||||||
ASDisplayNodeAssert(!CGPointIsNull(sublayout.position), @"Invalid position is not allowed in sublayout.");
|
ASDisplayNodeAssert(CGPointIsNull(sublayout.position) == NO, @"Invalid position is not allowed in sublayout.");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ASLayout *l = [super new];
|
_layoutableObject = layoutableObject;
|
||||||
if (l) {
|
|
||||||
l->_layoutableObject = layoutableObject;
|
|
||||||
|
|
||||||
if (!isValidForLayout(size.width) || !isValidForLayout(size.height)) {
|
if (!isValidForLayout(size.width) || !isValidForLayout(size.height)) {
|
||||||
ASDisplayNodeAssert(NO, @"layoutSize is invalid and unsafe to provide to Core Animation! Production will force to 0, 0. Size = %@, node = %@", NSStringFromCGSize(size), layoutableObject);
|
ASDisplayNodeAssert(NO, @"layoutSize is invalid and unsafe to provide to Core Animation! Production will force to 0, 0. Size = %@, node = %@", NSStringFromCGSize(size), layoutableObject);
|
||||||
@ -48,27 +60,40 @@ extern BOOL CGPointIsNull(CGPoint point)
|
|||||||
} else {
|
} else {
|
||||||
size = CGSizeMake(ASCeilPixelValue(size.width), ASCeilPixelValue(size.height));
|
size = CGSizeMake(ASCeilPixelValue(size.width), ASCeilPixelValue(size.height));
|
||||||
}
|
}
|
||||||
l->_constrainedSizeRange = sizeRange;
|
_constrainedSizeRange = sizeRange;
|
||||||
l->_size = size;
|
_size = size;
|
||||||
l->_dirty = NO;
|
_dirty = NO;
|
||||||
|
|
||||||
if (CGPointIsNull(position) == NO) {
|
if (CGPointIsNull(position) == NO) {
|
||||||
l->_position = CGPointMake(ASCeilPixelValue(position.x), ASCeilPixelValue(position.y));
|
_position = CGPointMake(ASCeilPixelValue(position.x), ASCeilPixelValue(position.y));
|
||||||
} else {
|
} else {
|
||||||
l->_position = position;
|
_position = position;
|
||||||
}
|
}
|
||||||
l->_sublayouts = [sublayouts copy];
|
_sublayouts = sublayouts != nil ? [sublayouts copy] : @[];
|
||||||
l->_flattened = flattened;
|
_flattened = NO;
|
||||||
|
|
||||||
NSMutableArray<ASLayout *> *result = [NSMutableArray array];
|
|
||||||
for (ASLayout *sublayout in l->_sublayouts) {
|
|
||||||
if (!sublayout.isFlattened) {
|
|
||||||
[result addObject:sublayout];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
l->_immediateSublayouts = result;
|
|
||||||
}
|
}
|
||||||
return l;
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert(NO, @"Use the designated initializer");
|
||||||
|
return [self init];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Class Constructors
|
||||||
|
|
||||||
|
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
||||||
|
constrainedSizeRange:(ASSizeRange)sizeRange
|
||||||
|
size:(CGSize)size
|
||||||
|
position:(CGPoint)position
|
||||||
|
sublayouts:(NSArray *)sublayouts
|
||||||
|
{
|
||||||
|
return [[self alloc] initWithLayoutableObject:layoutableObject
|
||||||
|
constrainedSizeRange:sizeRange
|
||||||
|
size:size
|
||||||
|
position:position
|
||||||
|
sublayouts:sublayouts];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
||||||
@ -80,8 +105,7 @@ extern BOOL CGPointIsNull(CGPoint point)
|
|||||||
constrainedSizeRange:sizeRange
|
constrainedSizeRange:sizeRange
|
||||||
size:size
|
size:size
|
||||||
position:CGPointNull
|
position:CGPointNull
|
||||||
sublayouts:sublayouts
|
sublayouts:sublayouts];
|
||||||
flattened:NO];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
+ (instancetype)layoutWithLayoutableObject:(id<ASLayoutable>)layoutableObject
|
||||||
@ -103,53 +127,61 @@ extern BOOL CGPointIsNull(CGPoint point)
|
|||||||
constrainedSizeRange:sizeRange
|
constrainedSizeRange:sizeRange
|
||||||
size:size
|
size:size
|
||||||
position:CGPointNull
|
position:CGPointNull
|
||||||
sublayouts:sublayouts
|
sublayouts:sublayouts];
|
||||||
flattened:YES];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ASLayout *)flattenedLayoutUsingPredicateBlock:(BOOL (^)(ASLayout *))predicateBlock
|
+ (instancetype)layoutWithLayout:(ASLayout *)layout position:(CGPoint)position
|
||||||
|
{
|
||||||
|
return [self layoutWithLayoutableObject:layout.layoutableObject
|
||||||
|
constrainedSizeRange:layout.constrainedSizeRange
|
||||||
|
size:layout.size
|
||||||
|
position:position
|
||||||
|
sublayouts:layout.sublayouts];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Layout Flattening
|
||||||
|
|
||||||
|
- (ASLayout *)filteredNodeLayoutTree
|
||||||
{
|
{
|
||||||
NSMutableArray *flattenedSublayouts = [NSMutableArray array];
|
NSMutableArray *flattenedSublayouts = [NSMutableArray array];
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
ASLayout *layout;
|
ASLayout *layout;
|
||||||
CGPoint absolutePosition;
|
CGPoint absolutePosition;
|
||||||
BOOL visited;
|
|
||||||
BOOL flattened;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Queue used to keep track of sublayouts while traversing this layout in a BFS fashion.
|
// Queue used to keep track of sublayouts while traversing this layout in a BFS fashion.
|
||||||
std::queue<Context> queue;
|
std::queue<Context> queue;
|
||||||
queue.push({self, CGPointMake(0, 0), NO, NO});
|
queue.push({self, CGPointMake(0, 0)});
|
||||||
|
|
||||||
while (!queue.empty()) {
|
while (!queue.empty()) {
|
||||||
Context &context = queue.front();
|
Context context = queue.front();
|
||||||
if (context.visited) {
|
queue.pop();
|
||||||
queue.pop();
|
|
||||||
} else {
|
if (self != context.layout && context.layout.type == ASLayoutableTypeDisplayNode) {
|
||||||
context.visited = YES;
|
ASLayout *layout = [ASLayout layoutWithLayout:context.layout position:context.absolutePosition];
|
||||||
|
layout.flattened = YES;
|
||||||
if (predicateBlock(context.layout)) {
|
[flattenedSublayouts addObject:layout];
|
||||||
[flattenedSublayouts addObject:[ASLayout layoutWithLayoutableObject:context.layout.layoutableObject
|
}
|
||||||
constrainedSizeRange:context.layout.constrainedSizeRange
|
|
||||||
size:context.layout.size
|
for (ASLayout *sublayout in context.layout.sublayouts) {
|
||||||
position:context.absolutePosition
|
if (sublayout.isFlattened == NO) {
|
||||||
sublayouts:nil
|
queue.push({sublayout, context.absolutePosition + sublayout.position});
|
||||||
flattened:context.flattened]];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ASLayout *sublayout in context.layout.sublayouts) {
|
|
||||||
// Mark layout trees that have already been flattened for future identification of immediate sublayouts
|
|
||||||
BOOL flattened = context.flattened ? : context.layout.flattened;
|
|
||||||
queue.push({sublayout, context.absolutePosition + sublayout.position, NO, flattened});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [ASLayout flattenedLayoutWithLayoutableObject:_layoutableObject
|
return [ASLayout layoutWithLayoutableObject:_layoutableObject
|
||||||
constrainedSizeRange:_constrainedSizeRange
|
constrainedSizeRange:_constrainedSizeRange
|
||||||
size:_size
|
size:_size
|
||||||
sublayouts:flattenedSublayouts];
|
sublayouts:flattenedSublayouts];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Accessors
|
||||||
|
|
||||||
|
- (ASLayoutableType)type
|
||||||
|
{
|
||||||
|
return _layoutableObject.layoutableType;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGRect)frame
|
- (CGRect)frame
|
||||||
|
|||||||
@ -34,7 +34,8 @@
|
|||||||
@implementation ASLayoutSpec
|
@implementation ASLayoutSpec
|
||||||
|
|
||||||
// these dynamic properties all defined in ASLayoutOptionsPrivate.m
|
// these dynamic properties all defined in ASLayoutOptionsPrivate.m
|
||||||
@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender, sizeRange, layoutPosition;
|
@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis,
|
||||||
|
alignSelf, ascender, descender, sizeRange, layoutPosition, layoutableType;
|
||||||
@synthesize isFinalLayoutable = _isFinalLayoutable;
|
@synthesize isFinalLayoutable = _isFinalLayoutable;
|
||||||
|
|
||||||
- (instancetype)init
|
- (instancetype)init
|
||||||
@ -48,6 +49,11 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (ASLayoutableType)layoutableType
|
||||||
|
{
|
||||||
|
return ASLayoutableTypeLayoutSpec;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Layout
|
#pragma mark - Layout
|
||||||
|
|
||||||
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
|
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
|
||||||
|
|||||||
@ -21,6 +21,11 @@
|
|||||||
@class ASLayout;
|
@class ASLayout;
|
||||||
@class ASLayoutSpec;
|
@class ASLayoutSpec;
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, ASLayoutableType) {
|
||||||
|
ASLayoutableTypeLayoutSpec,
|
||||||
|
ASLayoutableTypeDisplayNode
|
||||||
|
};
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,6 +46,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
*/
|
*/
|
||||||
@protocol ASLayoutable <ASEnvironment, ASStackLayoutable, ASStaticLayoutable, ASLayoutablePrivate, ASLayoutableExtensibility>
|
@protocol ASLayoutable <ASEnvironment, ASStackLayoutable, ASStaticLayoutable, ASLayoutablePrivate, ASLayoutableExtensibility>
|
||||||
|
|
||||||
|
@property (nonatomic, readonly) ASLayoutableType layoutableType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract Calculate a layout based on given size range.
|
* @abstract Calculate a layout based on given size range.
|
||||||
*
|
*
|
||||||
@ -50,7 +57,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
*/
|
*/
|
||||||
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize;
|
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize;
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - Layout options from the Layoutable Protocols
|
#pragma mark - Layout options from the Layoutable Protocols
|
||||||
|
|
||||||
#pragma mark - ASStackLayoutable
|
#pragma mark - ASStackLayoutable
|
||||||
|
|||||||
@ -67,7 +67,7 @@
|
|||||||
}
|
}
|
||||||
if (_previousLayout) {
|
if (_previousLayout) {
|
||||||
NSIndexSet *insertions, *deletions;
|
NSIndexSet *insertions, *deletions;
|
||||||
[_previousLayout.immediateSublayouts asdk_diffWithArray:_pendingLayout.immediateSublayouts
|
[_previousLayout.sublayouts asdk_diffWithArray:_pendingLayout.sublayouts
|
||||||
insertions:&insertions
|
insertions:&insertions
|
||||||
deletions:&deletions
|
deletions:&deletions
|
||||||
compareBlock:^BOOL(ASLayout *lhs, ASLayout *rhs) {
|
compareBlock:^BOOL(ASLayout *lhs, ASLayout *rhs) {
|
||||||
@ -80,7 +80,7 @@
|
|||||||
&_removedSubnodes,
|
&_removedSubnodes,
|
||||||
&_removedSubnodePositions);
|
&_removedSubnodePositions);
|
||||||
} else {
|
} else {
|
||||||
NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [_pendingLayout.immediateSublayouts count])];
|
NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [_pendingLayout.sublayouts count])];
|
||||||
findNodesInLayoutAtIndexes(_pendingLayout, indexes, &_insertedSubnodes, &_insertedSubnodePositions);
|
findNodesInLayoutAtIndexes(_pendingLayout, indexes, &_insertedSubnodes, &_insertedSubnodePositions);
|
||||||
_removedSubnodes = nil;
|
_removedSubnodes = nil;
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ static inline void findNodesInLayoutAtIndexesWithFilteredNodes(ASLayout *layout,
|
|||||||
std::vector<NSUInteger> positions = std::vector<NSUInteger>();
|
std::vector<NSUInteger> positions = std::vector<NSUInteger>();
|
||||||
NSUInteger idx = [indexes firstIndex];
|
NSUInteger idx = [indexes firstIndex];
|
||||||
while (idx != NSNotFound) {
|
while (idx != NSNotFound) {
|
||||||
ASDisplayNode *node = (ASDisplayNode *)layout.immediateSublayouts[idx].layoutableObject;
|
ASDisplayNode *node = (ASDisplayNode *)layout.sublayouts[idx].layoutableObject;
|
||||||
ASDisplayNodeCAssert(node, @"A flattened layout must consist exclusively of node sublayouts");
|
ASDisplayNodeCAssert(node, @"A flattened layout must consist exclusively of node sublayouts");
|
||||||
// Ignore the odd case in which a non-node sublayout is accessed and the type cast fails
|
// Ignore the odd case in which a non-node sublayout is accessed and the type cast fails
|
||||||
if (node != nil) {
|
if (node != nil) {
|
||||||
|
|||||||
@ -71,7 +71,7 @@ NSString * const ASTransitionContextToLayoutKey = @"org.asyncdisplaykit.ASTransi
|
|||||||
- (NSArray<ASDisplayNode *> *)subnodesForKey:(NSString *)key
|
- (NSArray<ASDisplayNode *> *)subnodesForKey:(NSString *)key
|
||||||
{
|
{
|
||||||
NSMutableArray<ASDisplayNode *> *subnodes = [NSMutableArray array];
|
NSMutableArray<ASDisplayNode *> *subnodes = [NSMutableArray array];
|
||||||
for (ASLayout *sublayout in [self layoutForKey:key].immediateSublayouts) {
|
for (ASLayout *sublayout in [self layoutForKey:key].sublayouts) {
|
||||||
[subnodes addObject:(ASDisplayNode *)sublayout.layoutableObject];
|
[subnodes addObject:(ASDisplayNode *)sublayout.layoutableObject];
|
||||||
}
|
}
|
||||||
return subnodes;
|
return subnodes;
|
||||||
|
|||||||
@ -65,9 +65,7 @@
|
|||||||
constrainedSizeRange:sizeRange
|
constrainedSizeRange:sizeRange
|
||||||
size:layout.size
|
size:layout.size
|
||||||
sublayouts:@[layout]];
|
sublayouts:@[layout]];
|
||||||
_layoutUnderTest = [layout flattenedLayoutUsingPredicateBlock:^BOOL(ASLayout *evaluatedLayout) {
|
_layoutUnderTest = [layout filteredNodeLayoutTree];
|
||||||
return [self.subnodes containsObject:(ASDisplayNode *)evaluatedLayout.layoutableObject];
|
|
||||||
}];
|
|
||||||
self.frame = CGRectMake(0, 0, _layoutUnderTest.size.width, _layoutUnderTest.size.height);
|
self.frame = CGRectMake(0, 0, _layoutUnderTest.size.width, _layoutUnderTest.size.height);
|
||||||
[self measure:_layoutUnderTest.size];
|
[self measure:_layoutUnderTest.size];
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user