Remove ASLayoutChild. ASLayout now has a position property defaults to (NAN, NAN).

This commit is contained in:
Huy Nguyen
2015-06-30 17:10:17 +07:00
parent e74823bbee
commit 4799a9d206
11 changed files with 79 additions and 54 deletions

View File

@@ -1426,8 +1426,8 @@ static NSInteger incrementIfFound(NSInteger i) {
subnodeSize.width, subnodeSize.height);
}
for (ASLayoutChild *child in context.layout.children) {
stack.push({child.layout, context.absolutePosition + child.position, NO});
for (ASLayout *child in context.layout.children) {
stack.push({child, context.absolutePosition + child.position, NO});
}
}
}

View File

@@ -44,14 +44,16 @@
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
{
ASLayout *contentsLayout = [_child calculateLayoutThatFits:constrainedSize];
contentsLayout.position = CGPointZero;
NSMutableArray *children = [NSMutableArray arrayWithCapacity:2];
if (_background) {
// Size background to exactly the same size.
ASLayout *backgroundLayout = [_background calculateLayoutThatFits:{contentsLayout.size, contentsLayout.size}];
[children addObject:[ASLayoutChild newWithPosition:{0,0} layout:backgroundLayout]];
backgroundLayout.position = CGPointZero;
[children addObject:backgroundLayout];
}
[children addObject:[ASLayoutChild newWithPosition:{0,0} layout:contentsLayout]];
[children addObject:contentsLayout];
return [ASLayout newWithLayoutableObject:self size:contentsLayout.size children:children];
}

View File

@@ -67,14 +67,12 @@
// Compute the centered postion for the child
BOOL shouldCenterAlongX = (_centeringOptions & ASCenterLayoutNodeCenteringX);
BOOL shouldCenterAlongY = (_centeringOptions & ASCenterLayoutNodeCenteringY);
const CGPoint childPosition = {
childLayout.position = {
ASRoundPixelValue(shouldCenterAlongX ? (size.width - childLayout.size.width) * 0.5f : 0),
ASRoundPixelValue(shouldCenterAlongY ? (size.height - childLayout.size.height) * 0.5f : 0)
};
return [ASLayout newWithLayoutableObject:self
size:size
children:@[[ASLayoutChild newWithPosition:childPosition layout:childLayout]]];
return [ASLayout newWithLayoutableObject:self size:size children:@[childLayout]];
}
@end

View File

@@ -99,9 +99,10 @@ static CGFloat centerInset(CGFloat outer, CGFloat inner)
constrainedSize.max.height -
(finite(_insets.bottom,
centerInset(constrainedSize.max.height, childLayout.size.height)) + childLayout.size.height));
return [ASLayout newWithLayoutableObject:self
size:computedSize
children:@[[ASLayoutChild newWithPosition:{x,y} layout:childLayout]]];
childLayout.position = CGPointMake(x, y);
return [ASLayout newWithLayoutableObject:self size:computedSize children:@[childLayout]];
}
@end

View File

@@ -12,35 +12,45 @@
#import <AsyncDisplayKit/ASAssert.h>
#import <AsyncDisplayKit/ASLayoutable.h>
/** Represents the computed size of a layout node, as well as the computed sizes and positions of its children. */
extern CGPoint const CGPointNull;
extern BOOL CGPointIsNull(CGPoint point);
/** Represents a computed immutable layout tree. */
@interface ASLayout : NSObject
@property (nonatomic, readonly) id<ASLayoutable> layoutableObject;
@property (nonatomic, readonly) CGSize size;
/**
* Each item is of type ASLayoutChild.
* Position parent (if any). Default to CGPointNull.
*
* @discussion Before being used as a child layout, this property must be set and no longer equal CGPointNull.
*
* @discussion Unlike all other properties, this property is read-write because often by initializaion time, it has yet been determined.
* To enforce immutability, this property can be set once and only once.
*
*/
@property (nonatomic, readwrite) CGPoint position;
/**
* Array of ASLayout children. Each child must have a valid non-null position.
*/
@property (nonatomic, readonly) NSArray *children;
+ (instancetype)newWithLayoutableObject:(id<ASLayoutable>)layoutableObject
size:(CGSize)size
position:(CGPoint)position
children:(NSArray *)children;
/**
* Convenience that does not have any children.
* Convenience that has CGPointNull position.
*/
+ (instancetype)newWithLayoutableObject:(id<ASLayoutable>)layoutableObject
size:(CGSize)size
children:(NSArray *)children;
/**
* Convenience that has CGPointNull position and no children.
*/
+ (instancetype)newWithLayoutableObject:(id<ASLayoutable>)layoutableObject size:(CGSize)size;
@end
@interface ASLayoutChild : NSObject
@property (nonatomic, readonly) CGPoint position;
@property (nonatomic, readonly) ASLayout *layout;
/**
* Designated initializer
*/
+ (instancetype)newWithPosition:(CGPoint)position layout:(ASLayout *)layout;
@end

View File

@@ -9,39 +9,53 @@
*/
#import "ASLayout.h"
#import "ASAssert.h"
CGPoint const CGPointNull = {NAN, NAN};
extern BOOL CGPointIsNull(CGPoint point)
{
return isnan(point.x) && isnan(point.y);
}
@implementation ASLayout
+ (instancetype)newWithLayoutableObject:(id<ASLayoutable>)layoutableObject
size:(CGSize)size
position:(CGPoint)position
children:(NSArray *)children
{
for (ASLayout *child in children) {
ASDisplayNodeAssert(!CGPointIsNull(child.position), @"Invalid position is not allowed in children.");
}
ASLayout *l = [super new];
if (l) {
l->_layoutableObject = layoutableObject;
l->_size = size;
l->_position = position;
l->_children = [children copy];
}
return l;
}
+ (instancetype)newWithLayoutableObject:(id<ASLayoutable>)layoutableObject
size:(CGSize)size
children:(NSArray *)children
{
return [self newWithLayoutableObject:layoutableObject size:size position:CGPointNull children:children];
}
+ (instancetype)newWithLayoutableObject:(id<ASLayoutable>)layoutableObject size:(CGSize)size
{
return [self newWithLayoutableObject:layoutableObject size:size children:nil];
}
@end
@implementation ASLayoutChild
+ (instancetype)newWithPosition:(CGPoint)position layout:(ASLayout *)layout
- (void)setPosition:(CGPoint)position
{
ASLayoutChild *c = [super new];
if (c) {
c->_position = position;
c->_layout = layout;
}
return c;
ASDisplayNodeAssert(CGPointIsNull(_position), @"Position can be set once and only once.");
ASDisplayNodeAssert(!CGPointIsNull(position), @"Position must not be set to null.");
_position = position;
}
@end

View File

@@ -41,10 +41,12 @@
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
{
ASLayout *contentsLayout = [_child calculateLayoutThatFits:constrainedSize];
NSMutableArray *layoutChildren = [NSMutableArray arrayWithObject:[ASLayoutChild newWithPosition:{0, 0} layout:contentsLayout]];
contentsLayout.position = CGPointZero;
NSMutableArray *layoutChildren = [NSMutableArray arrayWithObject:contentsLayout];
if (_overlay) {
ASLayout *overlayLayout = [_overlay calculateLayoutThatFits:{contentsLayout.size, contentsLayout.size}];
[layoutChildren addObject:[ASLayoutChild newWithPosition:{0, 0} layout:overlayLayout]];
overlayLayout.position = CGPointZero;
[layoutChildren addObject:overlayLayout];
}
return [ASLayout newWithLayoutableObject:self size:contentsLayout.size children:layoutChildren];

View File

@@ -68,9 +68,8 @@
// If there is no max size in *either* dimension, we can't apply the ratio, so just pass our size range through.
const ASSizeRange childRange = (bestSize == sizeOptions.end()) ? constrainedSize : ASSizeRangeMake(*bestSize, *bestSize);
ASLayout *childLayout = [_child calculateLayoutThatFits:childRange];
return [ASLayout newWithLayoutableObject:self
size:childLayout.size
children:@[[ASLayoutChild newWithPosition:{0, 0} layout:childLayout]]];
childLayout.position = CGPointZero;
return [ASLayout newWithLayoutableObject:self size:childLayout.size children:@[childLayout]];
}
@end

View File

@@ -68,22 +68,22 @@
ASSizeRange childConstraint = ASRelativeSizeRangeEqualToRelativeSizeRange(ASRelativeSizeRangeUnconstrained, child.size)
? ASSizeRangeMake({0, 0}, autoMaxSize)
: ASRelativeSizeRangeResolve(child.size, size);
ASLayoutChild *layoutChild = [ASLayoutChild newWithPosition:child.position
layout:[child.node calculateLayoutThatFits:childConstraint]];
[layoutChildren addObject:layoutChild];
ASLayout *childLayout = [child.node calculateLayoutThatFits:childConstraint];
childLayout.position = child.position;
[layoutChildren addObject:childLayout];
}
if (isnan(size.width)) {
size.width = constrainedSize.min.width;
for (ASLayoutChild *child in layoutChildren) {
size.width = MAX(size.width, child.position.x + child.layout.size.width);
for (ASLayout *child in layoutChildren) {
size.width = MAX(size.width, child.position.x + child.size.width);
}
}
if (isnan(size.height)) {
size.height = constrainedSize.min.height;
for (ASLayoutChild *child in layoutChildren) {
size.height = MAX(size.height, child.position.y + child.layout.size.height);
for (ASLayout *child in layoutChildren) {
size.height = MAX(size.height, child.position.y + child.size.height);
}
}

View File

@@ -15,7 +15,7 @@
/** Represents a set of laid out and positioned stack layout children. */
struct ASStackPositionedLayout {
const std::vector<ASLayoutChild *> children;
const std::vector<ASLayout *> children;
const CGFloat crossSize;
/** Given an unpositioned layout, computes the positions each child should be placed at. */

View File

@@ -47,16 +47,15 @@ static ASStackPositionedLayout stackedLayout(const ASStackLayoutNodeStyle &style
CGPoint p = directionPoint(style.direction, offset, 0);
BOOL first = YES;
auto stackedChildren = AS::map(unpositionedLayout.items, [&](const ASStackUnpositionedItem &l) -> ASLayoutChild *{
auto stackedChildren = AS::map(unpositionedLayout.items, [&](const ASStackUnpositionedItem &l) -> ASLayout *{
p = p + directionPoint(style.direction, l.child.spacingBefore, 0);
if (!first) {
p = p + directionPoint(style.direction, style.spacing, 0);
}
first = NO;
ASLayoutChild *c = [ASLayoutChild newWithPosition:p + directionPoint(style.direction, 0, crossOffset(style, l, crossSize))
layout:l.layout];
l.layout.position = p + directionPoint(style.direction, 0, crossOffset(style, l, crossSize));
p = p + directionPoint(style.direction, stackDimension(style.direction, l.layout.size) + l.child.spacingAfter, 0);
return c;
return l.layout;
});
return {stackedChildren, crossSize};
}