Moved ASLayoutable* properties into ASLayoutOptions class

This commit is contained in:
rcancro
2015-08-28 09:36:22 -07:00
parent 61b72d2c46
commit 15b3fd6eab
25 changed files with 370 additions and 188 deletions

View File

@@ -235,6 +235,10 @@
9C49C3701B853961000B0DD5 /* ASStackLayoutable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C49C36E1B853957000B0DD5 /* ASStackLayoutable.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9C49C3701B853961000B0DD5 /* ASStackLayoutable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C49C36E1B853957000B0DD5 /* ASStackLayoutable.h */; settings = {ATTRIBUTES = (Public, ); }; };
9C6BB3B21B8CC9C200F13F52 /* ASStaticLayoutable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C6BB3B01B8CC9C200F13F52 /* ASStaticLayoutable.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9C6BB3B21B8CC9C200F13F52 /* ASStaticLayoutable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C6BB3B01B8CC9C200F13F52 /* ASStaticLayoutable.h */; settings = {ATTRIBUTES = (Public, ); }; };
9C6BB3B31B8CC9C200F13F52 /* ASStaticLayoutable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C6BB3B01B8CC9C200F13F52 /* ASStaticLayoutable.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9C6BB3B31B8CC9C200F13F52 /* ASStaticLayoutable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C6BB3B01B8CC9C200F13F52 /* ASStaticLayoutable.h */; settings = {ATTRIBUTES = (Public, ); }; };
9C5FA3511B8F6ADF00A62714 /* ASLayoutOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C5FA34F1B8F6ADF00A62714 /* ASLayoutOptions.h */; settings = {ATTRIBUTES = (Public, ); }; };
9C5FA3521B8F6ADF00A62714 /* ASLayoutOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C5FA34F1B8F6ADF00A62714 /* ASLayoutOptions.h */; settings = {ATTRIBUTES = (Public, ); }; };
9C5FA3531B8F6ADF00A62714 /* ASLayoutOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C5FA3501B8F6ADF00A62714 /* ASLayoutOptions.m */; };
9C5FA3541B8F6ADF00A62714 /* ASLayoutOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C5FA3501B8F6ADF00A62714 /* ASLayoutOptions.m */; };
9F06E5CD1B4CAF4200F015D8 /* ASCollectionViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.m */; }; 9F06E5CD1B4CAF4200F015D8 /* ASCollectionViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.m */; };
AC21EC101B3D0BF600C8B19A /* ASStackLayoutDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = AC21EC0F1B3D0BF600C8B19A /* ASStackLayoutDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; AC21EC101B3D0BF600C8B19A /* ASStackLayoutDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = AC21EC0F1B3D0BF600C8B19A /* ASStackLayoutDefines.h */; settings = {ATTRIBUTES = (Public, ); }; };
AC3C4A511A1139C100143C57 /* ASCollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = AC3C4A4F1A1139C100143C57 /* ASCollectionView.h */; settings = {ATTRIBUTES = (Public, ); }; }; AC3C4A511A1139C100143C57 /* ASCollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = AC3C4A4F1A1139C100143C57 /* ASCollectionView.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -583,6 +587,8 @@
9C3061051B857EC400D0530B /* ASBaselineLayoutSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASBaselineLayoutSpec.mm; path = AsyncDisplayKit/Layout/ASBaselineLayoutSpec.mm; sourceTree = "<group>"; }; 9C3061051B857EC400D0530B /* ASBaselineLayoutSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASBaselineLayoutSpec.mm; path = AsyncDisplayKit/Layout/ASBaselineLayoutSpec.mm; sourceTree = "<group>"; };
9C49C36E1B853957000B0DD5 /* ASStackLayoutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStackLayoutable.h; path = AsyncDisplayKit/Layout/ASStackLayoutable.h; sourceTree = "<group>"; }; 9C49C36E1B853957000B0DD5 /* ASStackLayoutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStackLayoutable.h; path = AsyncDisplayKit/Layout/ASStackLayoutable.h; sourceTree = "<group>"; };
9C6BB3B01B8CC9C200F13F52 /* ASStaticLayoutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStaticLayoutable.h; path = AsyncDisplayKit/Layout/ASStaticLayoutable.h; sourceTree = "<group>"; }; 9C6BB3B01B8CC9C200F13F52 /* ASStaticLayoutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStaticLayoutable.h; path = AsyncDisplayKit/Layout/ASStaticLayoutable.h; sourceTree = "<group>"; };
9C5FA34F1B8F6ADF00A62714 /* ASLayoutOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutOptions.h; path = AsyncDisplayKit/Layout/ASLayoutOptions.h; sourceTree = "<group>"; };
9C5FA3501B8F6ADF00A62714 /* ASLayoutOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASLayoutOptions.m; path = AsyncDisplayKit/Layout/ASLayoutOptions.m; sourceTree = "<group>"; };
9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCollectionViewTests.m; sourceTree = "<group>"; }; 9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCollectionViewTests.m; sourceTree = "<group>"; };
AC21EC0F1B3D0BF600C8B19A /* ASStackLayoutDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStackLayoutDefines.h; path = AsyncDisplayKit/Layout/ASStackLayoutDefines.h; sourceTree = "<group>"; }; AC21EC0F1B3D0BF600C8B19A /* ASStackLayoutDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStackLayoutDefines.h; path = AsyncDisplayKit/Layout/ASStackLayoutDefines.h; sourceTree = "<group>"; };
AC3C4A4F1A1139C100143C57 /* ASCollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionView.h; sourceTree = "<group>"; }; AC3C4A4F1A1139C100143C57 /* ASCollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionView.h; sourceTree = "<group>"; };
@@ -1001,6 +1007,8 @@
ACF6ED191B17843500DA7C62 /* ASStaticLayoutSpec.mm */, ACF6ED191B17843500DA7C62 /* ASStaticLayoutSpec.mm */,
9C3061041B857EC400D0530B /* ASBaselineLayoutSpec.h */, 9C3061041B857EC400D0530B /* ASBaselineLayoutSpec.h */,
9C3061051B857EC400D0530B /* ASBaselineLayoutSpec.mm */, 9C3061051B857EC400D0530B /* ASBaselineLayoutSpec.mm */,
9C5FA34F1B8F6ADF00A62714 /* ASLayoutOptions.h */,
9C5FA3501B8F6ADF00A62714 /* ASLayoutOptions.m */,
); );
name = Layout; name = Layout;
path = ..; path = ..;
@@ -1068,6 +1076,7 @@
058D0A49195D05CB00B7D73C /* ASControlNode+Subclasses.h in Headers */, 058D0A49195D05CB00B7D73C /* ASControlNode+Subclasses.h in Headers */,
058D0A4A195D05CB00B7D73C /* ASDisplayNode.h in Headers */, 058D0A4A195D05CB00B7D73C /* ASDisplayNode.h in Headers */,
1950C4491A3BB5C1005C8279 /* ASEqualityHelpers.h in Headers */, 1950C4491A3BB5C1005C8279 /* ASEqualityHelpers.h in Headers */,
9C5FA3511B8F6ADF00A62714 /* ASLayoutOptions.h in Headers */,
058D0A4B195D05CB00B7D73C /* ASDisplayNode.mm in Headers */, 058D0A4B195D05CB00B7D73C /* ASDisplayNode.mm in Headers */,
430E7C8F1B4C23F100697A4C /* ASIndexPath.h in Headers */, 430E7C8F1B4C23F100697A4C /* ASIndexPath.h in Headers */,
058D0A4C195D05CB00B7D73C /* ASDisplayNode+Subclasses.h in Headers */, 058D0A4C195D05CB00B7D73C /* ASDisplayNode+Subclasses.h in Headers */,
@@ -1201,6 +1210,7 @@
B35062391B010EFD0018CF92 /* ASThread.h in Headers */, B35062391B010EFD0018CF92 /* ASThread.h in Headers */,
B35062131B010EFD0018CF92 /* ASBasicImageDownloader.h in Headers */, B35062131B010EFD0018CF92 /* ASBasicImageDownloader.h in Headers */,
34EFC7791B701D3600AD841F /* ASLayoutSpecUtilities.h in Headers */, 34EFC7791B701D3600AD841F /* ASLayoutSpecUtilities.h in Headers */,
9C5FA3521B8F6ADF00A62714 /* ASLayoutOptions.h in Headers */,
34EFC76A1B701CE600AD841F /* ASLayoutSpec.h in Headers */, 34EFC76A1B701CE600AD841F /* ASLayoutSpec.h in Headers */,
B35062221B010EFD0018CF92 /* ASMultidimensionalArrayUtils.h in Headers */, B35062221B010EFD0018CF92 /* ASMultidimensionalArrayUtils.h in Headers */,
B350625B1B010F070018CF92 /* ASEqualityHelpers.h in Headers */, B350625B1B010F070018CF92 /* ASEqualityHelpers.h in Headers */,
@@ -1461,6 +1471,7 @@
ACF6ED2E1B17843500DA7C62 /* ASRatioLayoutSpec.mm in Sources */, ACF6ED2E1B17843500DA7C62 /* ASRatioLayoutSpec.mm in Sources */,
058D0A18195D050800B7D73C /* _ASDisplayLayer.mm in Sources */, 058D0A18195D050800B7D73C /* _ASDisplayLayer.mm in Sources */,
ACF6ED321B17843500DA7C62 /* ASStaticLayoutSpec.mm in Sources */, ACF6ED321B17843500DA7C62 /* ASStaticLayoutSpec.mm in Sources */,
9C5FA3531B8F6ADF00A62714 /* ASLayoutOptions.m in Sources */,
ACF6ED2C1B17843500DA7C62 /* ASOverlayLayoutSpec.mm in Sources */, ACF6ED2C1B17843500DA7C62 /* ASOverlayLayoutSpec.mm in Sources */,
058D0A2C195D050800B7D73C /* ASSentinel.m in Sources */, 058D0A2C195D050800B7D73C /* ASSentinel.m in Sources */,
205F0E221B376416007741D0 /* CGRect+ASConvenience.m in Sources */, 205F0E221B376416007741D0 /* CGRect+ASConvenience.m in Sources */,
@@ -1588,6 +1599,7 @@
B350621C1B010EFD0018CF92 /* ASFlowLayoutController.mm in Sources */, B350621C1B010EFD0018CF92 /* ASFlowLayoutController.mm in Sources */,
B35062231B010EFD0018CF92 /* ASMultidimensionalArrayUtils.mm in Sources */, B35062231B010EFD0018CF92 /* ASMultidimensionalArrayUtils.mm in Sources */,
509E68641B3AEDB7009B9150 /* ASCollectionViewLayoutController.mm in Sources */, 509E68641B3AEDB7009B9150 /* ASCollectionViewLayoutController.mm in Sources */,
9C5FA3541B8F6ADF00A62714 /* ASLayoutOptions.m in Sources */,
B350621E1B010EFD0018CF92 /* ASHighlightOverlayLayer.mm in Sources */, B350621E1B010EFD0018CF92 /* ASHighlightOverlayLayer.mm in Sources */,
B35062271B010EFD0018CF92 /* ASRangeController.mm in Sources */, B35062271B010EFD0018CF92 /* ASRangeController.mm in Sources */,
18C2ED831B9B7DE800F627B3 /* ASCollectionNode.m in Sources */, 18C2ED831B9B7DE800F627B3 /* ASCollectionNode.m in Sources */,

View File

@@ -13,7 +13,7 @@
#import <AsyncDisplayKit/ASDealloc2MainObject.h> #import <AsyncDisplayKit/ASDealloc2MainObject.h>
#import <AsyncDisplayKit/ASDimension.h> #import <AsyncDisplayKit/ASDimension.h>
#import <AsyncDisplayKit/ASStackLayoutable.h> #import <AsyncDisplayKit/ASLayoutable.h>
/** /**
* UIView creation block. Used to create the backing view of a new display node. * UIView creation block. Used to create the backing view of a new display node.
@@ -40,7 +40,7 @@ typedef CALayer *(^ASDisplayNodeLayerBlock)();
* *
*/ */
@interface ASDisplayNode : ASDealloc2MainObject <ASStackLayoutable> @interface ASDisplayNode : ASDealloc2MainObject <ASLayoutable>
/** @name Initializing a node object */ /** @name Initializing a node object */

View File

@@ -41,12 +41,6 @@
@implementation ASDisplayNode @implementation ASDisplayNode
@synthesize spacingBefore = _spacingBefore;
@synthesize spacingAfter = _spacingAfter;
@synthesize flexGrow = _flexGrow;
@synthesize flexShrink = _flexShrink;
@synthesize flexBasis = _flexBasis;
@synthesize alignSelf = _alignSelf;
@synthesize preferredFrameSize = _preferredFrameSize; @synthesize preferredFrameSize = _preferredFrameSize;
BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector) BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector)
@@ -155,7 +149,6 @@ void ASDisplayNodeRespectThreadAffinityOfNode(ASDisplayNode *node, void (^block)
} }
_methodOverrides = overrides; _methodOverrides = overrides;
_flexBasis = ASRelativeDimensionUnconstrained;
_preferredFrameSize = CGSizeZero; _preferredFrameSize = CGSizeZero;
} }

View File

@@ -7,7 +7,6 @@
*/ */
#import <AsyncDisplayKit/ASControlNode.h> #import <AsyncDisplayKit/ASControlNode.h>
#import <AsyncDisplayKit/ASBaselineLayoutable.h>
@protocol ASTextNodeDelegate; @protocol ASTextNodeDelegate;
@@ -30,7 +29,7 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) {
@abstract Draws interactive rich text. @abstract Draws interactive rich text.
@discussion Backed by TextKit. @discussion Backed by TextKit.
*/ */
@interface ASTextNode : ASControlNode <ASBaselineLayoutable> @interface ASTextNode : ASControlNode
/** /**
@abstract The attributed string to show. @abstract The attributed string to show.

View File

@@ -17,7 +17,6 @@
#import <AsyncDisplayKit/ASTextNodeTextKitHelpers.h> #import <AsyncDisplayKit/ASTextNodeTextKitHelpers.h>
#import <AsyncDisplayKit/ASDisplayNodeExtras.h> #import <AsyncDisplayKit/ASDisplayNodeExtras.h>
#import "ASInternalHelpers.h"
#import "ASTextNodeRenderer.h" #import "ASTextNodeRenderer.h"
#import "ASTextNodeShadower.h" #import "ASTextNodeShadower.h"
@@ -108,9 +107,6 @@ ASDISPLAYNODE_INLINE CGFloat ceilPixelValue(CGFloat f)
UILongPressGestureRecognizer *_longPressGestureRecognizer; UILongPressGestureRecognizer *_longPressGestureRecognizer;
} }
@synthesize ascender = _ascender;
@synthesize descender = _descender;
#pragma mark - NSObject #pragma mark - NSObject
- (instancetype)init - (instancetype)init
@@ -359,9 +355,6 @@ ASDISPLAYNODE_INLINE CGFloat ceilPixelValue(CGFloat f)
self.isAccessibilityElement = YES; self.isAccessibilityElement = YES;
} }
}); });
_ascender = round([[attributedString attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender] * ASScreenScale())/ASScreenScale();
_descender = round([[attributedString attribute:NSFontAttributeName atIndex:attributedString.length - 1 effectiveRange:NULL] descender] * ASScreenScale())/ASScreenScale();
} }
#pragma mark - Text Layout #pragma mark - Text Layout

View File

@@ -9,7 +9,7 @@
*/ */
#import <AsyncDisplayKit/ASStackLayoutSpec.h> #import <AsyncDisplayKit/ASStackLayoutSpec.h>
#import <AsyncDisplayKit/ASBaselineLayoutable.h> #import <AsyncDisplayKit/ASLayoutable.h>
typedef NS_ENUM(NSUInteger, ASBaselineLayoutBaselineAlignment) { typedef NS_ENUM(NSUInteger, ASBaselineLayoutBaselineAlignment) {
/** No baseline alignment. This is only valid for a vertical stack */ /** No baseline alignment. This is only valid for a vertical stack */
@@ -29,7 +29,7 @@ typedef NS_ENUM(NSUInteger, ASBaselineLayoutBaselineAlignment) {
If the spec is created with a vertical direction, a child's vertical spacing will be measured from its If the spec is created with a vertical direction, a child's vertical spacing will be measured from its
baseline instead of from the child's bounding box. baseline instead of from the child's bounding box.
*/ */
@interface ASBaselineLayoutSpec : ASLayoutSpec <ASBaselineLayoutable> @interface ASBaselineLayoutSpec : ASLayoutSpec
/** Specifies the direction children are stacked in. */ /** Specifies the direction children are stacked in. */
@property (nonatomic, assign) ASStackLayoutDirection direction; @property (nonatomic, assign) ASStackLayoutDirection direction;

View File

@@ -9,7 +9,6 @@
*/ */
#import "ASBaselineLayoutSpec.h" #import "ASBaselineLayoutSpec.h"
#import "ASStackLayoutable.h"
#import <numeric> #import <numeric>
#import <vector> #import <vector>
@@ -26,12 +25,6 @@
@implementation ASBaselineLayoutSpec @implementation ASBaselineLayoutSpec
{
ASDN::RecursiveMutex _propertyLock;
}
@synthesize ascender = _ascender;
@synthesize descender = _descender;
- (instancetype)initWithDirection:(ASStackLayoutDirection)direction spacing:(CGFloat)spacing baselineAlignment:(ASBaselineLayoutBaselineAlignment)baselineAlignment justifyContent:(ASStackLayoutJustifyContent)justifyContent alignItems:(ASStackLayoutAlignItems)alignItems children:(NSArray *)children - (instancetype)initWithDirection:(ASStackLayoutDirection)direction spacing:(CGFloat)spacing baselineAlignment:(ASBaselineLayoutBaselineAlignment)baselineAlignment justifyContent:(ASStackLayoutJustifyContent)justifyContent alignItems:(ASStackLayoutAlignItems)alignItems children:(NSArray *)children
{ {
@@ -61,8 +54,8 @@
ASStackLayoutSpecStyle stackStyle = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems}; ASStackLayoutSpecStyle stackStyle = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems};
ASBaselineLayoutSpecStyle style = { .baselineAlignment = _baselineAlignment, .stackLayoutStyle = stackStyle }; ASBaselineLayoutSpecStyle style = { .baselineAlignment = _baselineAlignment, .stackLayoutStyle = stackStyle };
std::vector<id<ASStackLayoutable>> stackChildren = std::vector<id<ASStackLayoutable>>(); std::vector<id<ASLayoutable>> stackChildren = std::vector<id<ASLayoutable>>();
for (id<ASStackLayoutable> child in self.children) { for (id<ASLayoutable> child in self.children) {
stackChildren.push_back(child); stackChildren.push_back(child);
} }
@@ -74,25 +67,11 @@
NSArray *sublayouts = [NSArray arrayWithObjects:&baselinePositionedLayout.sublayouts[0] count:baselinePositionedLayout.sublayouts.size()]; NSArray *sublayouts = [NSArray arrayWithObjects:&baselinePositionedLayout.sublayouts[0] count:baselinePositionedLayout.sublayouts.size()];
ASDN::MutexLocker l(_propertyLock);
_ascender = baselinePositionedLayout.ascender;
_descender = baselinePositionedLayout.descender;
return [ASLayout layoutWithLayoutableObject:self return [ASLayout layoutWithLayoutableObject:self
size:ASSizeRangeClamp(constrainedSize, finalSize) size:ASSizeRangeClamp(constrainedSize, finalSize)
sublayouts:sublayouts]; sublayouts:sublayouts];
} }
- (void)setChildren:(NSArray *)children
{
[super setChildren:children];
#if DEBUG
for (id<ASBaselineLayoutable> child in children) {
NSAssert(([child finalLayoutable] == child && [child conformsToProtocol:@protocol(ASBaselineLayoutable)]) || ([child finalLayoutable] != child && [[child finalLayoutable] conformsToProtocol:@protocol(ASBaselineLayoutable)]), @"child must conform to ASBaselineLayoutable");
}
#endif
}
- (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier - (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier
{ {
ASDisplayNodeAssert(NO, @"ASBaselineLayoutSpec only supports setChildren"); ASDisplayNodeAssert(NO, @"ASBaselineLayoutSpec only supports setChildren");

View File

@@ -6,9 +6,9 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*/ */
#import "ASStackLayoutable.h" #import <UIKit/UIKit.h>
@protocol ASBaselineLayoutable <ASStackLayoutable> @protocol ASBaselineLayoutable
/** /**
* @abstract The distance from the top of the layoutable object to its baseline * @abstract The distance from the top of the layoutable object to its baseline

View File

@@ -0,0 +1,49 @@
//
// ASLayoutOptions.h
// AsyncDisplayKit
//
// Created by Ricky Cancro on 8/27/15.
// Copyright (c) 2015 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol ASLayoutable;
#import <AsyncDisplayKit/ASBaselineLayoutable.h>
#import <AsyncDisplayKit/ASStackLayoutable.h>
#import <AsyncDisplayKit/ASStaticLayoutable.h>
@interface ASLayoutOptions : NSObject <ASBaselineLayoutable, ASStackLayoutable, ASStaticLayoutable, NSCopying>
- (instancetype)initWithLayoutable:(id<ASLayoutable>)layoutable;
- (void)setValuesFromLayoutable:(id<ASLayoutable>)layoutable;
@property (nonatomic, assign) BOOL isMutable;
#if DEBUG
@property (nonatomic, assign) NSUInteger changeMonitor;
#endif
#pragma mark - ASStackLayoutable
@property (nonatomic, readwrite) CGFloat spacingBefore;
@property (nonatomic, readwrite) CGFloat spacingAfter;
@property (nonatomic, readwrite) BOOL flexGrow;
@property (nonatomic, readwrite) BOOL flexShrink;
@property (nonatomic, readwrite) ASRelativeDimension flexBasis;
@property (nonatomic, readwrite) ASStackLayoutAlignSelf alignSelf;
#pragma mark - ASBaselineLayoutable
@property (nonatomic, readwrite) CGFloat ascender;
@property (nonatomic, readwrite) CGFloat descender;
#pragma mark - ASStaticLayoutable
@property (nonatomic, readwrite) ASRelativeSizeRange sizeRange;
@property (nonatomic, readwrite) CGPoint position;
- (void)setupDefaults;
@end

View File

@@ -0,0 +1,120 @@
//
// ASLayoutOptions.m
// AsyncDisplayKit
//
// Created by Ricky Cancro on 8/27/15.
// Copyright (c) 2015 Facebook. All rights reserved.
//
#import "ASLayoutOptions.h"
#import <AsyncDisplayKit/ASAssert.h>
#import <AsyncDisplayKit/ASTextNode.h>
#import "ASInternalHelpers.h"
#import <objc/runtime.h>
@implementation ASLayoutOptions
- (instancetype)initWithLayoutable:(id<ASLayoutable>)layoutable;
{
self = [super init];
if (self) {
[self setupDefaults];
[self setValuesFromLayoutable:layoutable];
#if DEBUG
[self addObserver:self forKeyPath:@"changeMonitor"
options:NSKeyValueObservingOptionNew
context:nil];
#endif
}
return self;
}
#if DEBUG
+ (NSSet *)keyPathsForValuesAffectingChangeMonitor
{
NSMutableSet *keys = [NSMutableSet set];
unsigned int count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
for (size_t i = 0; i < count; ++i) {
NSString *property = [NSString stringWithCString:property_getName(properties[i]) encoding:NSASCIIStringEncoding];
if ([property isEqualToString: @"observableSelf"] == NO) {
[keys addObject: property];
}
}
free(properties);
return keys;
}
#endif
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
#if DEBUG
if ([keyPath isEqualToString:@"changeMonitor"]) {
ASDisplayNodeAssert(self.isMutable, @"You cannot alter this class once it is marked as immutable");
} else
#endif
{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
#pragma mark - NSCopying
- (id)copyWithZone:(NSZone *)zone
{
ASLayoutOptions *copy = [[[self class] alloc] init];
copy.flexBasis = self.flexBasis;
copy.spacingAfter = self.spacingAfter;
copy.spacingBefore = self.spacingBefore;
copy.flexGrow = self.flexGrow;
copy.flexShrink = self.flexShrink;
copy.ascender = self.ascender;
copy.descender = self.descender;
copy.sizeRange = self.sizeRange;
copy.position = self.position;
return copy;
}
#pragma mark - Defaults
- (void)setupDefaults
{
_flexBasis = ASRelativeDimensionUnconstrained;
_spacingBefore = 0;
_spacingAfter = 0;
_flexGrow = NO;
_flexShrink = NO;
_alignSelf = ASStackLayoutAlignSelfAuto;
_ascender = 0;
_descender = 0;
_sizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(CGSizeZero), ASRelativeSizeMakeWithCGSize(CGSizeZero));
_position = CGPointZero;
}
// Do this here instead of in Node/Spec subclasses so that custom specs can set default values
- (void)setValuesFromLayoutable:(id<ASLayoutable>)layoutable
{
if ([layoutable isKindOfClass:[ASTextNode class]]) {
ASTextNode *textNode = (ASTextNode *)layoutable;
self.ascender = round([[textNode.attributedString attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender] * ASScreenScale())/ASScreenScale();
self.descender = round([[textNode.attributedString attribute:NSFontAttributeName atIndex:textNode.attributedString.length - 1 effectiveRange:NULL] descender] * ASScreenScale())/ASScreenScale();
}
if ([layoutable isKindOfClass:[ASDisplayNode class]]) {
ASDisplayNode *displayNode = (ASDisplayNode *)layoutable;
self.sizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(displayNode.preferredFrameSize), ASRelativeSizeMakeWithCGSize(displayNode.preferredFrameSize));
self.position = displayNode.frame.origin;
}
}
@end

View File

@@ -8,10 +8,10 @@
* *
*/ */
#import <AsyncDisplayKit/ASStackLayoutable.h> #import <AsyncDisplayKit/ASLayoutable.h>
/** A layout spec is an immutable object that describes a layout, loosely inspired by React. */ /** A layout spec is an immutable object that describes a layout, loosely inspired by React. */
@interface ASLayoutSpec : NSObject <ASStackLayoutable> @interface ASLayoutSpec : NSObject <ASLayoutable>
/** /**
Creation of a layout spec should only happen by a user in layoutSpecThatFits:. During that method, a Creation of a layout spec should only happen by a user in layoutSpecThatFits:. During that method, a
@@ -23,12 +23,15 @@
- (instancetype)init; - (instancetype)init;
- (void)setChild:(id<ASLayoutable>)child; - (void)setChild:(id<ASLayoutable>)child;
- (id<ASLayoutable>)child;
- (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier; - (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier;
- (id<ASLayoutable>)childForIdentifier:(NSString *)identifier;
- (void)setChildren:(NSArray *)children; - (void)setChildren:(NSArray *)children;
- (id<ASLayoutable>)child;
- (id<ASLayoutable>)childForIdentifier:(NSString *)identifier;
- (NSArray *)children; - (NSArray *)children;
+ (ASLayoutOptions *)layoutOptionsForChild:(id<ASLayoutable>)child;
+ (void)associateLayoutOptions:(ASLayoutOptions *)layoutOptions withChild:(id<ASLayoutable>)child;
+ (void)setLayoutOptionsClass:(Class)layoutOptionsClass;
@end @end

View File

@@ -16,6 +16,8 @@
#import "ASInternalHelpers.h" #import "ASInternalHelpers.h"
#import "ASLayout.h" #import "ASLayout.h"
#import <objc/runtime.h>
static NSString * const kDefaultChildKey = @"kDefaultChildKey"; static NSString * const kDefaultChildKey = @"kDefaultChildKey";
static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey"; static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey";
@@ -25,12 +27,6 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey";
@implementation ASLayoutSpec @implementation ASLayoutSpec
@synthesize spacingBefore = _spacingBefore;
@synthesize spacingAfter = _spacingAfter;
@synthesize flexGrow = _flexGrow;
@synthesize flexShrink = _flexShrink;
@synthesize flexBasis = _flexBasis;
@synthesize alignSelf = _alignSelf;
@synthesize layoutChildren = _layoutChildren; @synthesize layoutChildren = _layoutChildren;
- (instancetype)init - (instancetype)init
@@ -39,7 +35,6 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey";
return nil; return nil;
} }
_layoutChildren = [NSMutableDictionary dictionary]; _layoutChildren = [NSMutableDictionary dictionary];
_flexBasis = ASRelativeDimensionUnconstrained;
_isMutable = YES; _isMutable = YES;
return self; return self;
} }
@@ -61,15 +56,34 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey";
[self setChild:child forIdentifier:kDefaultChildKey]; [self setChild:child forIdentifier:kDefaultChildKey];
} }
- (id<ASLayoutable>)child
{
return self.layoutChildren[kDefaultChildKey];
}
- (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier - (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier
{ {
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
self.layoutChildren[identifier] = [child finalLayoutable]; ASLayoutOptions *layoutOptions = [ASLayoutSpec layoutOptionsForChild:child];
layoutOptions.isMutable = NO;
self.layoutChildren[identifier] = child;
}
- (void)setChildren:(NSArray *)children
{
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
NSMutableArray *finalChildren = [NSMutableArray arrayWithCapacity:children.count];
for (id<ASLayoutable> child in children) {
ASLayoutOptions *layoutOptions = [ASLayoutSpec layoutOptionsForChild:child];
id<ASLayoutable> finalLayoutable = [child finalLayoutable];
layoutOptions.isMutable = NO;
if (finalLayoutable != child) {
ASLayoutOptions *finalLayoutOptions = [layoutOptions copy];
finalLayoutOptions.isMutable = NO;
[ASLayoutSpec associateLayoutOptions:finalLayoutOptions withChild:finalLayoutable];
}
[finalChildren addObject:finalLayoutable];
}
self.layoutChildren[kDefaultChildrenKey] = [NSArray arrayWithArray:finalChildren];
} }
- (id<ASLayoutable>)childForIdentifier:(NSString *)identifier - (id<ASLayoutable>)childForIdentifier:(NSString *)identifier
@@ -77,14 +91,9 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey";
return self.layoutChildren[identifier]; return self.layoutChildren[identifier];
} }
- (void)setChildren:(NSArray *)children - (id<ASLayoutable>)child
{ {
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); return self.layoutChildren[kDefaultChildKey];
NSMutableArray *finalChildren = [NSMutableArray arrayWithCapacity:children.count];
for (id<ASLayoutable> child in children) {
[finalChildren addObject:[child finalLayoutable]];
}
self.layoutChildren[kDefaultChildrenKey] = [NSArray arrayWithArray:finalChildren];
} }
- (NSArray *)children - (NSArray *)children
@@ -92,4 +101,35 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey";
return self.layoutChildren[kDefaultChildrenKey]; return self.layoutChildren[kDefaultChildrenKey];
} }
static Class gLayoutOptionsClass = [ASLayoutOptions class];
+ (void)setLayoutOptionsClass:(Class)layoutOptionsClass
{
gLayoutOptionsClass = layoutOptionsClass;
}
+ (ASLayoutOptions *)optionsForChild:(id<ASLayoutable>)child
{
ASLayoutOptions *layoutOptions = [[gLayoutOptionsClass alloc] init];;
[layoutOptions setValuesFromLayoutable:child];
layoutOptions.isMutable = NO;
return layoutOptions;
}
+ (void)associateLayoutOptions:(ASLayoutOptions *)layoutOptions withChild:(id<ASLayoutable>)child
{
objc_setAssociatedObject(child, @selector(setChild:), layoutOptions, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
+ (ASLayoutOptions *)layoutOptionsForChild:(id<ASLayoutable>)child
{
ASLayoutOptions *layoutOptions = objc_getAssociatedObject(child, @selector(setChild:));
if (layoutOptions == nil) {
layoutOptions = [self optionsForChild:child];
[self associateLayoutOptions:layoutOptions withChild:child];
}
return objc_getAssociatedObject(child, @selector(setChild:));
}
@end @end

View File

@@ -10,6 +10,7 @@
#import <AsyncDisplayKit/ASDimension.h> #import <AsyncDisplayKit/ASDimension.h>
#import <AsyncDisplayKit/ASStackLayoutDefines.h> #import <AsyncDisplayKit/ASStackLayoutDefines.h>
#import <AsyncDisplayKit/ASLayoutOptions.h>
@class ASLayout; @class ASLayout;
@class ASLayoutSpec; @class ASLayoutSpec;

View File

@@ -72,17 +72,6 @@
_spacing = spacing; _spacing = spacing;
} }
- (void)setChildren:(NSArray *)children
{
[super setChildren:children];
#if DEBUG
for (id<ASStackLayoutable> child in children) {
ASDisplayNodeAssert(([child finalLayoutable] == child && [child conformsToProtocol:@protocol(ASStackLayoutable)]) || ([child finalLayoutable] != child && [[child finalLayoutable] conformsToProtocol:@protocol(ASStackLayoutable)]), @"child must conform to ASBaselineLayoutable");
}
#endif
}
- (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier - (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier
{ {
ASDisplayNodeAssert(NO, @"ASStackLayoutSpec only supports setChildren"); ASDisplayNodeAssert(NO, @"ASStackLayoutSpec only supports setChildren");
@@ -91,9 +80,8 @@
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
{ {
ASStackLayoutSpecStyle style = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems}; ASStackLayoutSpecStyle style = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems};
std::vector<id<ASStackLayoutable>> stackChildren = std::vector<id<ASStackLayoutable>>(); std::vector<id<ASLayoutable>> stackChildren = std::vector<id<ASLayoutable>>();
for (id<ASStackLayoutable> child in self.children) { for (id<ASLayoutable> child in self.children) {
NSAssert([child conformsToProtocol:@protocol(ASStackLayoutable)], @"Child must implement ASStackLayoutable");
stackChildren.push_back(child); stackChildren.push_back(child);
} }

View File

@@ -8,9 +8,10 @@
* *
*/ */
#import <AsyncDisplayKit/ASLayoutable.h> #import <AsyncDisplayKit/ASDimension.h>
#import <AsyncDisplayKit/ASStackLayoutDefines.h>
@protocol ASStackLayoutable <ASLayoutable> @protocol ASStackLayoutable <NSObject>
/** /**
* @abstract Additional space to place before this object in the stacking direction. * @abstract Additional space to place before this object in the stacking direction.

View File

@@ -36,17 +36,6 @@
return self; return self;
} }
- (void)setChildren:(NSArray *)children
{
[super setChildren:children];
#if DEBUG
for (id<ASStaticLayoutable> child in children) {
ASDisplayNodeAssert(([child finalLayoutable] == child && [child conformsToProtocol:@protocol(ASStaticLayoutable)]) || ([child finalLayoutable] != child && [[child finalLayoutable] conformsToProtocol:@protocol(ASStaticLayoutable)]), @"child must conform to ASStaticLayoutable");
}
#endif
}
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
{ {
CGSize size = { CGSize size = {
@@ -55,16 +44,17 @@
}; };
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:self.children.count]; NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:self.children.count];
for (id<ASStaticLayoutable> child in self.children) { for (id<ASLayoutable> child in self.children) {
ASLayoutOptions *layoutOptions = [ASLayoutSpec layoutOptionsForChild:child];
CGSize autoMaxSize = { CGSize autoMaxSize = {
constrainedSize.max.width - child.position.x, constrainedSize.max.width - layoutOptions.position.x,
constrainedSize.max.height - child.position.y constrainedSize.max.height - layoutOptions.position.y
}; };
ASSizeRange childConstraint = ASRelativeSizeRangeEqualToRelativeSizeRange(ASRelativeSizeRangeUnconstrained, child.sizeRange) ASSizeRange childConstraint = ASRelativeSizeRangeEqualToRelativeSizeRange(ASRelativeSizeRangeUnconstrained, layoutOptions.sizeRange)
? ASSizeRangeMake({0, 0}, autoMaxSize) ? ASSizeRangeMake({0, 0}, autoMaxSize)
: ASRelativeSizeRangeResolve(child.sizeRange, size); : ASRelativeSizeRangeResolve(layoutOptions.sizeRange, size);
ASLayout *sublayout = [child measureWithSizeRange:childConstraint]; ASLayout *sublayout = [child measureWithSizeRange:childConstraint];
sublayout.position = child.position; sublayout.position = layoutOptions.position;
[sublayouts addObject:sublayout]; [sublayouts addObject:sublayout];
} }

View File

@@ -8,10 +8,9 @@
* *
*/ */
#import <AsyncDisplayKit/ASLayoutable.h>
#import <AsyncDisplayKit/ASRelativeSize.h> #import <AsyncDisplayKit/ASRelativeSize.h>
@protocol ASStaticLayoutable<ASLayoutable> @protocol ASStaticLayoutable
/** /**
If specified, the child's size is restricted according to this size. Percentages are resolved relative to the static layout spec. If specified, the child's size is restricted according to this size. Percentages are resolved relative to the static layout spec.

View File

@@ -15,15 +15,14 @@
static CGFloat baselineForItem(const ASBaselineLayoutSpecStyle &style, static CGFloat baselineForItem(const ASBaselineLayoutSpecStyle &style,
const ASLayout *layout) { const ASLayout *layout) {
ASLayoutOptions *layoutOptions = [ASLayoutSpec layoutOptionsForChild:layout.layoutableObject];
__weak id<ASBaselineLayoutable> child = (id<ASBaselineLayoutable>) layout.layoutableObject;
switch (style.baselineAlignment) { switch (style.baselineAlignment) {
case ASBaselineLayoutBaselineAlignmentNone: case ASBaselineLayoutBaselineAlignmentNone:
return 0; return 0;
case ASBaselineLayoutBaselineAlignmentFirst: case ASBaselineLayoutBaselineAlignmentFirst:
return child.ascender; return layoutOptions.ascender;
case ASBaselineLayoutBaselineAlignmentLast: case ASBaselineLayoutBaselineAlignmentLast:
return layout.size.height + child.descender; return layout.size.height + layoutOptions.descender;
} }
} }
@@ -34,10 +33,10 @@ static CGFloat baselineOffset(const ASBaselineLayoutSpecStyle &style,
const CGFloat maxBaseline) const CGFloat maxBaseline)
{ {
if (style.stackLayoutStyle.direction == ASStackLayoutDirectionHorizontal) { if (style.stackLayoutStyle.direction == ASStackLayoutDirectionHorizontal) {
__weak id<ASBaselineLayoutable> child = (id<ASBaselineLayoutable>)l.layoutableObject; ASLayoutOptions *layoutOptions = [ASLayoutSpec layoutOptionsForChild:l.layoutableObject];
switch (style.baselineAlignment) { switch (style.baselineAlignment) {
case ASBaselineLayoutBaselineAlignmentFirst: case ASBaselineLayoutBaselineAlignmentFirst:
return maxAscender - child.ascender; return maxAscender - layoutOptions.ascender;
case ASBaselineLayoutBaselineAlignmentLast: case ASBaselineLayoutBaselineAlignmentLast:
return maxBaseline - baselineForItem(style, l); return maxBaseline - baselineForItem(style, l);
case ASBaselineLayoutBaselineAlignmentNone: case ASBaselineLayoutBaselineAlignmentNone:
@@ -91,9 +90,11 @@ ASBaselinePositionedLayout ASBaselinePositionedLayout::compute(const ASStackPosi
our layoutSpec to have it so that it can be baseline aligned with another text node or baseline layout spec. our layoutSpec to have it so that it can be baseline aligned with another text node or baseline layout spec.
*/ */
const auto ascenderIt = std::max_element(positionedLayout.sublayouts.begin(), positionedLayout.sublayouts.end(), [&](const ASLayout *a, const ASLayout *b){ const auto ascenderIt = std::max_element(positionedLayout.sublayouts.begin(), positionedLayout.sublayouts.end(), [&](const ASLayout *a, const ASLayout *b){
return ((id<ASBaselineLayoutable>)a.layoutableObject).ascender < ((id<ASBaselineLayoutable>)b.layoutableObject).ascender; ASLayoutOptions *layoutOptionsA = [ASLayoutSpec layoutOptionsForChild:a.layoutableObject];
ASLayoutOptions *layoutOptionsB = [ASLayoutSpec layoutOptionsForChild:b.layoutableObject];
return layoutOptionsA.ascender < layoutOptionsB.ascender;
}); });
const CGFloat maxAscender = baselineIt == positionedLayout.sublayouts.end() ? 0 : ((id<ASBaselineLayoutable>)(*ascenderIt).layoutableObject).ascender; const CGFloat maxAscender = baselineIt == positionedLayout.sublayouts.end() ? 0 : [ASLayoutSpec layoutOptionsForChild:(*ascenderIt).layoutableObject].ascender;
/* /*
Step 3: Take each child and update its layout position based on the baseline offset. Step 3: Take each child and update its layout position based on the baseline offset.
@@ -106,8 +107,8 @@ ASBaselinePositionedLayout ASBaselinePositionedLayout::compute(const ASStackPosi
CGPoint p = CGPointZero; CGPoint p = CGPointZero;
BOOL first = YES; BOOL first = YES;
auto stackedChildren = AS::map(positionedLayout.sublayouts, [&](ASLayout *l) -> ASLayout *{ auto stackedChildren = AS::map(positionedLayout.sublayouts, [&](ASLayout *l) -> ASLayout *{
__weak id<ASBaselineLayoutable> child = (id<ASBaselineLayoutable>) l.layoutableObject; ASLayoutOptions *layoutOptions = [ASLayoutSpec layoutOptionsForChild:l.layoutableObject];
p = p + directionPoint(stackStyle.direction, child.spacingBefore, 0); p = p + directionPoint(stackStyle.direction, layoutOptions.spacingBefore, 0);
if (first) { if (first) {
// if this is the first item use the previously computed start point // if this is the first item use the previously computed start point
p = l.position; p = l.position;
@@ -124,9 +125,9 @@ ASBaselinePositionedLayout ASBaselinePositionedLayout::compute(const ASStackPosi
// node from baselines and not bounding boxes. // node from baselines and not bounding boxes.
CGFloat spacingAfterBaseline = 0; CGFloat spacingAfterBaseline = 0;
if (stackStyle.direction == ASStackLayoutDirectionVertical) { if (stackStyle.direction == ASStackLayoutDirectionVertical) {
spacingAfterBaseline = child.descender; spacingAfterBaseline = layoutOptions.descender;
} }
p = p + directionPoint(stackStyle.direction, stackDimension(stackStyle.direction, l.size) + child.spacingAfter + spacingAfterBaseline, 0); p = p + directionPoint(stackStyle.direction, stackDimension(stackStyle.direction, l.size) + layoutOptions.spacingAfter + spacingAfterBaseline, 0);
return l; return l;
}); });
@@ -151,12 +152,12 @@ ASBaselinePositionedLayout ASBaselinePositionedLayout::compute(const ASStackPosi
/* /*
Step 5: finally, we must find the smallest descender (descender is negative). This is since ASBaselineLayoutSpec implements Step 5: finally, we must find the smallest descender (descender is negative). This is since ASBaselineLayoutSpec implements
ASBaselineLayoutable and needs an ascender and descender to lay itself out properly. ASLayoutable and needs an ascender and descender to lay itself out properly.
*/ */
const auto descenderIt = std::max_element(stackedChildren.begin(), stackedChildren.end(), [&](const ASLayout *a, const ASLayout *b){ const auto descenderIt = std::max_element(stackedChildren.begin(), stackedChildren.end(), [&](const ASLayout *a, const ASLayout *b){
return a.position.y + a.size.height < b.position.y + b.size.height; return a.position.y + a.size.height < b.position.y + b.size.height;
}); });
const CGFloat minDescender = descenderIt == stackedChildren.end() ? 0 : ((id<ASBaselineLayoutable>)(*descenderIt).layoutableObject).descender; const CGFloat minDescender = descenderIt == stackedChildren.end() ? 0 : [ASLayoutSpec layoutOptionsForChild:(*descenderIt).layoutableObject].descender;
return {stackedChildren, crossSize, maxAscender, minDescender}; return {stackedChildren, crossSize, maxAscender, minDescender};
} }

View File

@@ -19,7 +19,8 @@ static CGFloat crossOffset(const ASStackLayoutSpecStyle &style,
const ASStackUnpositionedItem &l, const ASStackUnpositionedItem &l,
const CGFloat crossSize) const CGFloat crossSize)
{ {
switch (alignment(l.child.alignSelf, style.alignItems)) { ASLayoutOptions *layoutOptions = [ASLayoutSpec layoutOptionsForChild:l.child];
switch (alignment(layoutOptions.alignSelf, style.alignItems)) {
case ASStackLayoutAlignItemsEnd: case ASStackLayoutAlignItemsEnd:
return crossSize - crossDimension(style.direction, l.layout.size); return crossSize - crossDimension(style.direction, l.layout.size);
case ASStackLayoutAlignItemsCenter: case ASStackLayoutAlignItemsCenter:
@@ -48,14 +49,15 @@ static ASStackPositionedLayout stackedLayout(const ASStackLayoutSpecStyle &style
CGPoint p = directionPoint(style.direction, offset, 0); CGPoint p = directionPoint(style.direction, offset, 0);
BOOL first = YES; BOOL first = YES;
auto stackedChildren = AS::map(unpositionedLayout.items, [&](const ASStackUnpositionedItem &l) -> ASLayout *{ auto stackedChildren = AS::map(unpositionedLayout.items, [&](const ASStackUnpositionedItem &l) -> ASLayout *{
p = p + directionPoint(style.direction, l.child.spacingBefore, 0); ASLayoutOptions *layoutOptions = [ASLayoutSpec layoutOptionsForChild:l.child];
p = p + directionPoint(style.direction, layoutOptions.spacingBefore, 0);
if (!first) { if (!first) {
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));
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) + layoutOptions.spacingAfter, 0);
return l.layout; return l.layout;
}); });
return {stackedChildren, crossSize}; return {stackedChildren, crossSize};

View File

@@ -16,7 +16,7 @@
struct ASStackUnpositionedItem { struct ASStackUnpositionedItem {
/** The original source child. */ /** The original source child. */
id<ASStackLayoutable> child; id<ASLayoutable> child;
/** The proposed layout. */ /** The proposed layout. */
ASLayout *layout; ASLayout *layout;
}; };
@@ -31,7 +31,7 @@ struct ASStackUnpositionedLayout {
const CGFloat violation; const CGFloat violation;
/** Given a set of children, computes the unpositioned layouts for those children. */ /** Given a set of children, computes the unpositioned layouts for those children. */
static ASStackUnpositionedLayout compute(const std::vector<id<ASStackLayoutable>> &children, static ASStackUnpositionedLayout compute(const std::vector<id<ASLayoutable>> &children,
const ASStackLayoutSpecStyle &style, const ASStackLayoutSpecStyle &style,
const ASSizeRange &sizeRange); const ASSizeRange &sizeRange);
}; };

View File

@@ -18,14 +18,15 @@
/** /**
Sizes the child given the parameters specified, and returns the computed layout. Sizes the child given the parameters specified, and returns the computed layout.
*/ */
static ASLayout *crossChildLayout(const id<ASStackLayoutable> child, static ASLayout *crossChildLayout(const id<ASLayoutable> child,
const ASStackLayoutSpecStyle style, const ASStackLayoutSpecStyle style,
const CGFloat stackMin, const CGFloat stackMin,
const CGFloat stackMax, const CGFloat stackMax,
const CGFloat crossMin, const CGFloat crossMin,
const CGFloat crossMax) const CGFloat crossMax)
{ {
const ASStackLayoutAlignItems alignItems = alignment(child.alignSelf, style.alignItems); ASLayoutOptions *layoutOptions = [ASLayoutSpec layoutOptionsForChild:child];
const ASStackLayoutAlignItems alignItems = alignment(layoutOptions.alignSelf, style.alignItems);
// stretched children will have a cross dimension of at least crossMin // stretched children will have a cross dimension of at least crossMin
const CGFloat childCrossMin = alignItems == ASStackLayoutAlignItemsStretch ? crossMin : 0; const CGFloat childCrossMin = alignItems == ASStackLayoutAlignItemsStretch ? crossMin : 0;
const ASSizeRange childSizeRange = directionSizeRange(style.direction, stackMin, stackMax, childCrossMin, crossMax); const ASSizeRange childSizeRange = directionSizeRange(style.direction, stackMin, stackMax, childCrossMin, crossMax);
@@ -75,7 +76,8 @@ static void stretchChildrenAlongCrossDimension(std::vector<ASStackUnpositionedIt
const CGFloat childCrossMax = it == layouts.end() ? 0 : crossDimension(style.direction, it->layout.size); const CGFloat childCrossMax = it == layouts.end() ? 0 : crossDimension(style.direction, it->layout.size);
for (auto &l : layouts) { for (auto &l : layouts) {
const ASStackLayoutAlignItems alignItems = alignment(l.child.alignSelf, style.alignItems); ASLayoutOptions *layoutOptions = [ASLayoutSpec layoutOptionsForChild:l.child];
const ASStackLayoutAlignItems alignItems = alignment(layoutOptions.alignSelf, style.alignItems);
const CGFloat cross = crossDimension(style.direction, l.layout.size); const CGFloat cross = crossDimension(style.direction, l.layout.size);
const CGFloat stack = stackDimension(style.direction, l.layout.size); const CGFloat stack = stackDimension(style.direction, l.layout.size);
@@ -111,7 +113,8 @@ static CGFloat computeStackDimensionSum(const std::vector<ASStackUnpositionedIte
// Start from default spacing between each child: // Start from default spacing between each child:
children.empty() ? 0 : style.spacing * (children.size() - 1), children.empty() ? 0 : style.spacing * (children.size() - 1),
[&](CGFloat x, const ASStackUnpositionedItem &l) { [&](CGFloat x, const ASStackUnpositionedItem &l) {
return x + l.child.spacingBefore + l.child.spacingAfter; ASLayoutOptions *layoutOptions = [ASLayoutSpec layoutOptionsForChild:l.child];
return x + layoutOptions.spacingBefore + layoutOptions.spacingAfter;
}); });
// Sum up the childrens' dimensions (including spacing) in the stack direction. // Sum up the childrens' dimensions (including spacing) in the stack direction.
@@ -180,22 +183,23 @@ static std::function<BOOL(const ASStackUnpositionedItem &)> isFlexibleInViolatio
if (fabs(violation) < kViolationEpsilon) { if (fabs(violation) < kViolationEpsilon) {
return [](const ASStackUnpositionedItem &l) { return NO; }; return [](const ASStackUnpositionedItem &l) { return NO; };
} else if (violation > 0) { } else if (violation > 0) {
return [](const ASStackUnpositionedItem &l) { return l.child.flexGrow; }; return [](const ASStackUnpositionedItem &l) { return [ASLayoutSpec layoutOptionsForChild:l.child].flexGrow; };
} else { } else {
return [](const ASStackUnpositionedItem &l) { return l.child.flexShrink; }; return [](const ASStackUnpositionedItem &l) { return [ASLayoutSpec layoutOptionsForChild:l.child].flexShrink; };
} }
} }
ASDISPLAYNODE_INLINE BOOL isFlexibleInBothDirections(id<ASStackLayoutable> child) ASDISPLAYNODE_INLINE BOOL isFlexibleInBothDirections(id<ASLayoutable> child)
{ {
return child.flexGrow && child.flexShrink; ASLayoutOptions *layoutOptions = [ASLayoutSpec layoutOptionsForChild:child];
return layoutOptions.flexGrow && layoutOptions.flexShrink;
} }
/** /**
If we have a single flexible (both shrinkable and growable) child, and our allowed size range is set to a specific If we have a single flexible (both shrinkable and growable) child, and our allowed size range is set to a specific
number then we may avoid the first "intrinsic" size calculation. number then we may avoid the first "intrinsic" size calculation.
*/ */
ASDISPLAYNODE_INLINE BOOL useOptimizedFlexing(const std::vector<id<ASStackLayoutable>> &children, ASDISPLAYNODE_INLINE BOOL useOptimizedFlexing(const std::vector<id<ASLayoutable>> &children,
const ASStackLayoutSpecStyle &style, const ASStackLayoutSpecStyle &style,
const ASSizeRange &sizeRange) const ASSizeRange &sizeRange)
{ {
@@ -283,7 +287,7 @@ static void flexChildrenAlongStackDimension(std::vector<ASStackUnpositionedItem>
Performs the first unconstrained layout of the children, generating the unpositioned items that are then flexed and Performs the first unconstrained layout of the children, generating the unpositioned items that are then flexed and
stretched. stretched.
*/ */
static std::vector<ASStackUnpositionedItem> layoutChildrenAlongUnconstrainedStackDimension(const std::vector<id<ASStackLayoutable>> &children, static std::vector<ASStackUnpositionedItem> layoutChildrenAlongUnconstrainedStackDimension(const std::vector<id<ASLayoutable>> &children,
const ASStackLayoutSpecStyle &style, const ASStackLayoutSpecStyle &style,
const ASSizeRange &sizeRange, const ASSizeRange &sizeRange,
const CGSize size, const CGSize size,
@@ -292,9 +296,10 @@ static std::vector<ASStackUnpositionedItem> layoutChildrenAlongUnconstrainedStac
const CGFloat minCrossDimension = crossDimension(style.direction, sizeRange.min); const CGFloat minCrossDimension = crossDimension(style.direction, sizeRange.min);
const CGFloat maxCrossDimension = crossDimension(style.direction, sizeRange.max); const CGFloat maxCrossDimension = crossDimension(style.direction, sizeRange.max);
return AS::map(children, [&](id<ASStackLayoutable> child) -> ASStackUnpositionedItem { return AS::map(children, [&](id<ASLayoutable> child) -> ASStackUnpositionedItem {
const BOOL isUnconstrainedFlexBasis = ASRelativeDimensionEqualToRelativeDimension(ASRelativeDimensionUnconstrained, child.flexBasis); ASLayoutOptions *layoutOptions = [ASLayoutSpec layoutOptionsForChild:child];
const CGFloat exactStackDimension = ASRelativeDimensionResolve(child.flexBasis, stackDimension(style.direction, size)); const BOOL isUnconstrainedFlexBasis = ASRelativeDimensionEqualToRelativeDimension(ASRelativeDimensionUnconstrained, layoutOptions.flexBasis);
const CGFloat exactStackDimension = ASRelativeDimensionResolve(layoutOptions.flexBasis, stackDimension(style.direction, size));
if (useOptimizedFlexing && isFlexibleInBothDirections(child)) { if (useOptimizedFlexing && isFlexibleInBothDirections(child)) {
return { child, [ASLayout layoutWithLayoutableObject:child size:{0, 0}] }; return { child, [ASLayout layoutWithLayoutableObject:child size:{0, 0}] };
@@ -312,7 +317,7 @@ static std::vector<ASStackUnpositionedItem> layoutChildrenAlongUnconstrainedStac
}); });
} }
ASStackUnpositionedLayout ASStackUnpositionedLayout::compute(const std::vector<id<ASStackLayoutable>> &children, ASStackUnpositionedLayout ASStackUnpositionedLayout::compute(const std::vector<id<ASLayoutable>> &children,
const ASStackLayoutSpecStyle &style, const ASStackLayoutSpecStyle &style,
const ASSizeRange &sizeRange) const ASSizeRange &sizeRange)
{ {

View File

@@ -94,7 +94,7 @@ static NSString *suffixForCenteringOptions(ASCenterLayoutSpecCenteringOptions ce
ASDisplayNode *backgroundNode = ASDisplayNodeWithBackgroundColor([UIColor redColor]); ASDisplayNode *backgroundNode = ASDisplayNodeWithBackgroundColor([UIColor redColor]);
ASStaticSizeDisplayNode *foregroundNode = ASDisplayNodeWithBackgroundColor([UIColor redColor]); ASStaticSizeDisplayNode *foregroundNode = ASDisplayNodeWithBackgroundColor([UIColor redColor]);
foregroundNode.staticSize = {10, 10}; foregroundNode.staticSize = {10, 10};
foregroundNode.flexGrow = YES; [ASLayoutSpec layoutOptionsForChild:foregroundNode].flexGrow = YES;
ASCenterLayoutSpec *layoutSpec = ASCenterLayoutSpec *layoutSpec =
[ASCenterLayoutSpec [ASCenterLayoutSpec

View File

@@ -41,8 +41,8 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
]; ];
for (ASStaticSizeDisplayNode *subnode in subnodes) { for (ASStaticSizeDisplayNode *subnode in subnodes) {
subnode.staticSize = subnodeSize; subnode.staticSize = subnodeSize;
subnode.flexGrow = flex; [ASLayoutSpec layoutOptionsForChild:subnode].flexGrow = flex;
subnode.flexShrink = flex; [ASLayoutSpec layoutOptionsForChild:subnode].flexShrink = flex;
} }
return subnodes; return subnodes;
} }
@@ -114,7 +114,7 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
ASStackLayoutSpecStyle style = {.direction = ASStackLayoutDirectionHorizontal}; ASStackLayoutSpecStyle style = {.direction = ASStackLayoutDirectionHorizontal};
NSArray *subnodes = defaultSubnodesWithSameSize({50, 50}, NO); NSArray *subnodes = defaultSubnodesWithSameSize({50, 50}, NO);
((ASDisplayNode *)subnodes[1]).flexShrink = YES; [ASLayoutSpec layoutOptionsForChild:((ASDisplayNode *)subnodes[1])].flexShrink = YES;
// Width is 75px--that's less than the sum of the widths of the children, which is 100px. // Width is 75px--that's less than the sum of the widths of the children, which is 100px.
static ASSizeRange kSize = {{75, 0}, {75, 150}}; static ASSizeRange kSize = {{75, 0}, {75, 150}};
@@ -204,23 +204,25 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70}; ((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90}; ((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 10; ASLayoutOptions *layoutOptions1 = [ASLayoutSpec layoutOptionsForChild:subnodes[1]];
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 20; ASLayoutOptions *layoutOptions2 = [ASLayoutSpec layoutOptionsForChild:subnodes[2]];
layoutOptions1.spacingBefore = 10;
layoutOptions2.spacingBefore = 20;
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingBefore"]; [self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingBefore"];
// Reset above spacing values // Reset above spacing values
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 0; layoutOptions1.spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 0; layoutOptions2.spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingAfter = 10; layoutOptions1.spacingAfter = 10;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingAfter = 20; layoutOptions2.spacingAfter = 20;
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingAfter"]; [self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingAfter"];
// Reset above spacing values // Reset above spacing values
((ASStaticSizeDisplayNode *)subnodes[1]).spacingAfter = 0; layoutOptions1.spacingAfter = 0;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingAfter = 0; layoutOptions2.spacingAfter = 0;
style.spacing = 10; style.spacing = 10;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = -10; layoutOptions1.spacingBefore = -10;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingAfter = -10; layoutOptions2.spacingAfter = -10;
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingBalancedOut"]; [self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingBalancedOut"];
} }
@@ -236,9 +238,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70}; ((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90}; ((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[0])].spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[1])].spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[2])].spacingBefore = 30;
// width 0-300px; height 300px // width 0-300px; height 300px
static ASSizeRange kVariableHeight = {{0, 300}, {300, 300}}; static ASSizeRange kVariableHeight = {{0, 300}, {300, 300}};
@@ -254,9 +256,10 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
subnode2.staticSize = {50, 50}; subnode2.staticSize = {50, 50};
ASRatioLayoutSpec *child1 = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.5 child:subnode1]; ASRatioLayoutSpec *child1 = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.5 child:subnode1];
child1.flexBasis = ASRelativeDimensionMakeWithPercent(1); ASLayoutOptions *layoutOptions1 = [ASLayoutSpec layoutOptionsForChild:child1];
child1.flexGrow = YES; layoutOptions1.flexBasis = ASRelativeDimensionMakeWithPercent(1);
child1.flexShrink = YES; layoutOptions1.flexGrow = YES;
layoutOptions1.flexShrink = YES;
static ASSizeRange kFixedWidth = {{150, 0}, {150, INFINITY}}; static ASSizeRange kFixedWidth = {{150, 0}, {150, INFINITY}};
[self testStackLayoutSpecWithStyle:style children:@[child1, subnode2] sizeRange:kFixedWidth subnodes:@[subnode1, subnode2] identifier:nil]; [self testStackLayoutSpecWithStyle:style children:@[child1, subnode2] sizeRange:kFixedWidth subnodes:@[subnode1, subnode2] identifier:nil];
@@ -271,11 +274,11 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
ASStaticSizeDisplayNode *subnode1 = ASDisplayNodeWithBackgroundColor([UIColor redColor]); ASStaticSizeDisplayNode *subnode1 = ASDisplayNodeWithBackgroundColor([UIColor redColor]);
subnode1.staticSize = {100, 100}; subnode1.staticSize = {100, 100};
subnode1.flexShrink = YES; [ASLayoutSpec layoutOptionsForChild:subnode1].flexShrink = YES;
ASStaticSizeDisplayNode *subnode2 = ASDisplayNodeWithBackgroundColor([UIColor blueColor]); ASStaticSizeDisplayNode *subnode2 = ASDisplayNodeWithBackgroundColor([UIColor blueColor]);
subnode2.staticSize = {50, 50}; subnode2.staticSize = {50, 50};
subnode2.flexShrink = YES; [ASLayoutSpec layoutOptionsForChild:subnode2].flexShrink = YES;
NSArray *subnodes = @[subnode1, subnode2]; NSArray *subnodes = @[subnode1, subnode2];
static ASSizeRange kFixedWidth = {{150, 0}, {150, 100}}; static ASSizeRange kFixedWidth = {{150, 0}, {150, 100}};
@@ -291,7 +294,7 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
ASStaticSizeDisplayNode *subnode2 = ASDisplayNodeWithBackgroundColor([UIColor blueColor]); ASStaticSizeDisplayNode *subnode2 = ASDisplayNodeWithBackgroundColor([UIColor blueColor]);
subnode2.staticSize = {50, 50}; subnode2.staticSize = {50, 50};
subnode2.alignSelf = ASStackLayoutAlignSelfCenter; [ASLayoutSpec layoutOptionsForChild:subnode2].alignSelf = ASStackLayoutAlignSelfCenter;
NSArray *subnodes = @[subnode1, subnode2]; NSArray *subnodes = @[subnode1, subnode2];
static ASSizeRange kFixedWidth = {{150, 0}, {150, INFINITY}}; static ASSizeRange kFixedWidth = {{150, 0}, {150, INFINITY}};
@@ -311,9 +314,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70}; ((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90}; ((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[0])].spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[1])].spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[2])].spacingBefore = 30;
static ASSizeRange kExactSize = {{300, 300}, {300, 300}}; static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil]; [self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
@@ -332,9 +335,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70}; ((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90}; ((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[0])].spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[1])].spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[2])].spacingBefore = 30;
static ASSizeRange kExactSize = {{300, 300}, {300, 300}}; static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil]; [self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
@@ -353,9 +356,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70}; ((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90}; ((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[0])].spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[1])].spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[2])].spacingBefore = 30;
static ASSizeRange kExactSize = {{300, 300}, {300, 300}}; static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil]; [self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
@@ -374,9 +377,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70}; ((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90}; ((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[0])].spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[1])].spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[2])].spacingBefore = 30;
static ASSizeRange kVariableSize = {{200, 200}, {300, 300}}; static ASSizeRange kVariableSize = {{200, 200}, {300, 300}};
// all children should be 200px wide // all children should be 200px wide
@@ -396,9 +399,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70}; ((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90}; ((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[0])].spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[1])].spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[2])].spacingBefore = 30;
static ASSizeRange kVariableSize = {{50, 50}, {300, 300}}; static ASSizeRange kVariableSize = {{50, 50}, {300, 300}};
// all children should be 150px wide // all children should be 150px wide
@@ -419,8 +422,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {150, 150}; ((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {150, 150};
for (ASStaticSizeDisplayNode *subnode in subnodes) { for (ASStaticSizeDisplayNode *subnode in subnodes) {
subnode.flexGrow = YES; ASLayoutOptions *layoutOptions = [ASLayoutSpec layoutOptionsForChild:subnode];
subnode.flexBasis = ASRelativeDimensionMakeWithPoints(10); layoutOptions.flexGrow = YES;
layoutOptions.flexBasis = ASRelativeDimensionMakeWithPoints(10);
} }
// width 300px; height 0-150px. // width 300px; height 0-150px.
@@ -439,12 +443,12 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
NSArray *subnodes = defaultSubnodesWithSameSize({50, 50}, NO); NSArray *subnodes = defaultSubnodesWithSameSize({50, 50}, NO);
for (ASStaticSizeDisplayNode *subnode in subnodes) { for (ASStaticSizeDisplayNode *subnode in subnodes) {
subnode.flexGrow = YES; [ASLayoutSpec layoutOptionsForChild:subnode].flexGrow = YES;
} }
// This should override the intrinsic size of 50pts and instead compute to 50% = 100pts. // This should override the intrinsic size of 50pts and instead compute to 50% = 100pts.
// The result should be that the red box is twice as wide as the blue and gree boxes after flexing. // The result should be that the red box is twice as wide as the blue and gree boxes after flexing.
((ASStaticSizeDisplayNode *)subnodes[0]).flexBasis = ASRelativeDimensionMakeWithPercent(0.5); [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[0])].flexBasis = ASRelativeDimensionMakeWithPercent(0.5);
static ASSizeRange kSize = {{200, 0}, {200, INFINITY}}; static ASSizeRange kSize = {{200, 0}, {200, INFINITY}};
[self testStackLayoutSpecWithStyle:style sizeRange:kSize subnodes:subnodes identifier:nil]; [self testStackLayoutSpecWithStyle:style sizeRange:kSize subnodes:subnodes identifier:nil];
@@ -460,7 +464,7 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {50, 50}; ((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {50, 50};
for (ASStaticSizeDisplayNode *subnode in subnodes) { for (ASStaticSizeDisplayNode *subnode in subnodes) {
subnode.flexBasis = ASRelativeDimensionMakeWithPoints(20); [ASLayoutSpec layoutOptionsForChild:subnode].flexBasis = ASRelativeDimensionMakeWithPoints(20);
} }
static ASSizeRange kSize = {{300, 0}, {300, 150}}; static ASSizeRange kSize = {{300, 0}, {300, 150}};
@@ -478,8 +482,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {3000, 3000}; ((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {3000, 3000};
ASRatioLayoutSpec *child2 = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.0 child:subnodes[2]]; ASRatioLayoutSpec *child2 = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.0 child:subnodes[2]];
child2.flexGrow = YES; ASLayoutOptions *layoutOptions2 = [ASLayoutSpec layoutOptionsForChild:child2];
child2.flexShrink = YES; layoutOptions2.flexGrow = YES;
layoutOptions2.flexShrink = YES;
// If cross axis stretching occurred *before* flexing, then the blue child would be stretched to 3000 points tall. // If cross axis stretching occurred *before* flexing, then the blue child would be stretched to 3000 points tall.
// Instead it should be stretched to 300 points tall, matching the red child and not overlapping the green inset. // Instead it should be stretched to 300 points tall, matching the red child and not overlapping the green inset.
@@ -504,13 +509,13 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
NSArray *subnodes = defaultSubnodes(); NSArray *subnodes = defaultSubnodes();
((ASStaticSizeDisplayNode *)subnodes[0]).staticSize = {300, 50}; ((ASStaticSizeDisplayNode *)subnodes[0]).staticSize = {300, 50};
((ASStaticSizeDisplayNode *)subnodes[0]).flexShrink = YES; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[0])].flexShrink = YES;
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 50}; ((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 50};
((ASStaticSizeDisplayNode *)subnodes[1]).flexShrink = NO; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[1])].flexShrink = NO;
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {200, 50}; ((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {200, 50};
((ASStaticSizeDisplayNode *)subnodes[2]).flexShrink = YES; [ASLayoutSpec layoutOptionsForChild:((ASStaticSizeDisplayNode *)subnodes[2])].flexShrink = YES;
// A width of 400px results in a violation of 200px. This is distributed equally among each flexible child, // A width of 400px results in a violation of 200px. This is distributed equally among each flexible child,
// causing both of them to be shrunk by 100px, resulting in widths of 300px, 100px, and 50px. // causing both of them to be shrunk by 100px, resulting in widths of 300px, 100px, and 50px.

View File

@@ -10,4 +10,4 @@ SPEC CHECKSUMS:
FBSnapshotTestCase: 3dc3899168747a0319c5278f5b3445c13a6532dd FBSnapshotTestCase: 3dc3899168747a0319c5278f5b3445c13a6532dd
OCMock: a6a7dc0e3997fb9f35d99f72528698ebf60d64f2 OCMock: a6a7dc0e3997fb9f35d99f72528698ebf60d64f2
COCOAPODS: 0.37.2 COCOAPODS: 0.35.0

View File

@@ -58,7 +58,9 @@
1A943BF0259746F18D6E423F /* Frameworks */, 1A943BF0259746F18D6E423F /* Frameworks */,
1AE410B73DA5C3BD087ACDD7 /* Pods */, 1AE410B73DA5C3BD087ACDD7 /* Pods */,
); );
indentWidth = 2;
sourceTree = "<group>"; sourceTree = "<group>";
tabWidth = 2;
}; };
05E2128219D4DB510098F589 /* Products */ = { 05E2128219D4DB510098F589 /* Products */ = {
isa = PBXGroup; isa = PBXGroup;