diff --git a/AsyncDisplayKit/ASCellNode.m b/AsyncDisplayKit/ASCellNode.m index 4273a10cc1..14b304086b 100644 --- a/AsyncDisplayKit/ASCellNode.m +++ b/AsyncDisplayKit/ASCellNode.m @@ -111,7 +111,7 @@ static const CGFloat kFontSize = 18.0f; static const CGFloat kHorizontalPadding = 15.0f; static const CGFloat kVerticalPadding = 11.0f; UIEdgeInsets insets = UIEdgeInsetsMake(kVerticalPadding, kHorizontalPadding, kVerticalPadding, kHorizontalPadding); - return [ASInsetLayoutSpec newWithInsets:insets child:_textNode]; + return [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:_textNode]; } - (void)setText:(NSString *)text diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index c02c053e25..ab1a644091 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1333,12 +1333,13 @@ static NSInteger incrementIfFound(NSInteger i) { { ASDisplayNodeAssertThreadAffinity(self); if (_methodOverrides & ASDisplayNodeMethodOverrideLayoutSpecThatFits) { - id layoutSpec = [self layoutSpecThatFits:constrainedSize]; + ASLayoutSpec *layoutSpec = [self layoutSpecThatFits:constrainedSize]; + layoutSpec.isMutable = NO; ASLayout *layout = [layoutSpec measureWithSizeRange:constrainedSize]; // Make sure layoutableObject of the root layout is `self`, so that the flattened layout will be structurally correct. if (layout.layoutableObject != self) { layout.position = CGPointZero; - layout = [ASLayout newWithLayoutableObject:self size:layout.size sublayouts:@[layout]]; + layout = [ASLayout layoutWithLayoutableObject:self size:layout.size sublayouts:@[layout]]; } return [layout flattenedLayoutUsingPredicateBlock:^BOOL(ASLayout *evaluatedLayout) { return [_subnodes containsObject:evaluatedLayout.layoutableObject]; @@ -1347,7 +1348,7 @@ static NSInteger incrementIfFound(NSInteger i) { // If neither -layoutSpecThatFits: nor -calculateSizeThatFits: is overridden by subclassses, preferredFrameSize should be used, // assume that the default implementation of -calculateSizeThatFits: returns it. CGSize size = [self calculateSizeThatFits:constrainedSize.max]; - return [ASLayout newWithLayoutableObject:self size:ASSizeRangeClamp(constrainedSize, size)]; + return [ASLayout layoutWithLayoutableObject:self size:ASSizeRangeClamp(constrainedSize, size)]; } } diff --git a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h index 508f7c8b28..ecc2e48473 100644 --- a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h @@ -15,11 +15,14 @@ */ @interface ASBackgroundLayoutSpec : ASLayoutSpec +@property (nonatomic, strong) id child; +@property (nonatomic, strong) id background; + /** @param child A child that is laid out to determine the size of this spec. If this is nil, then this method returns nil. @param background A layoutable object that is laid out behind the child. May be nil, in which case the background is omitted. */ -+ (instancetype)newWithChild:(id)child background:(id)background; ++ (instancetype)backgroundLayoutSpecWithChild:(id)child background:(id)background; @end diff --git a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm index ae03e78836..fd3cfce134 100644 --- a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm @@ -23,20 +23,22 @@ @implementation ASBackgroundLayoutSpec -+ (instancetype)newWithChild:(id)child background:(id)background +- (instancetype)initWithChild:(id)child background:(id)background { - if (child == nil) { + if (!(self = [super init])) { return nil; } - ASBackgroundLayoutSpec *spec = [super new]; - spec->_child = child; - spec->_background = background; - return spec; + + ASDisplayNodeAssertNotNil(child, @"Child cannot be nil"); + _child = child; + _background = background; + return self; } -+ (instancetype)new + ++ (instancetype)backgroundLayoutSpecWithChild:(id)child background:(id)background; { - ASDISPLAYNODE_NOT_DESIGNATED_INITIALIZER(); + return [[self alloc] initWithChild:child background:background]; } /** @@ -56,7 +58,19 @@ contentsLayout.position = CGPointZero; [sublayouts addObject:contentsLayout]; - return [ASLayout newWithLayoutableObject:self size:contentsLayout.size sublayouts:sublayouts]; + return [ASLayout layoutWithLayoutableObject:self size:contentsLayout.size sublayouts:sublayouts]; +} + +- (void)setBackground:(id)background +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _background = background; +} + +- (void)setChild:(id)child +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _child = child; } @end diff --git a/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.h b/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.h index ca59a0d00b..8b784a56c3 100644 --- a/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.h @@ -21,15 +21,6 @@ typedef NS_ENUM(NSUInteger, ASBaselineLayoutBaselineAlignment) { ASBaselineLayoutBaselineAlignmentLast, }; - -typedef struct { - /** Describes how the stack will be laid out */ - ASStackLayoutSpecStyle stackLayoutStyle; - - /** The type of baseline alignment */ - ASBaselineLayoutBaselineAlignment baselineAlignment; -} ASBaselineLayoutSpecStyle; - /** A specialized version of a stack layout that aligns its children on a baseline. This spec only works with ASBaselineLayoutable children. @@ -40,10 +31,33 @@ typedef struct { */ @interface ASBaselineLayoutSpec : ASLayoutSpec +/** Specifies the direction children are stacked in. */ +@property (nonatomic, assign) ASStackLayoutDirection direction; +/** The amount of space between each child. */ +@property (nonatomic, assign) CGFloat spacing; +/** The amount of space between each child. */ +@property (nonatomic, assign) ASStackLayoutJustifyContent justifyContent; +/** Orientation of children along cross axis */ +@property (nonatomic, assign) ASStackLayoutAlignItems alignItems; +/** The type of baseline alignment */ +@property (nonatomic, assign) ASBaselineLayoutBaselineAlignment baselineAlignment; + +- (void)addChild:(id)child; +- (void)addChildren:(NSArray *)children; + /** - @param style Specifies how children are laid out. - @param children ASTextLayoutable children to be positioned. + @param direction The direction of the stack view (horizontal or vertical) + @param spacing The spacing between the children + @param baselineAlignment The baseline to align to + @param justifyContent If no children are flexible, this describes how to fill any extra space + @param alignItems Orientation of the children along the cross axis + @param children ASLayoutable children to be positioned. */ -+ (instancetype)newWithStyle:(ASBaselineLayoutSpecStyle)style children:(NSArray *)children; ++ (instancetype)baselineLayoutSpecWithDirection:(ASStackLayoutDirection)direction + spacing:(CGFloat)spacing + baselineAlignment:(ASBaselineLayoutBaselineAlignment)baselineAlignment + justifyContent:(ASStackLayoutJustifyContent)justifyContent + alignItems:(ASStackLayoutAlignItems)alignItems + children:(NSArray *)children; @end diff --git a/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.mm b/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.mm index 5e1c78d2c6..670c69c991 100644 --- a/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.mm @@ -27,43 +27,47 @@ @implementation ASBaselineLayoutSpec { - ASBaselineLayoutSpecStyle _style; - std::vector> _stackChildren; + std::vector> _children; ASDN::RecursiveMutex _propertyLock; } @synthesize ascender = _ascender; @synthesize descender = _descender; -+ (instancetype)newWithStyle:(ASBaselineLayoutSpecStyle)style children:(NSArray *)children +- (instancetype)initWithDirection:(ASStackLayoutDirection)direction spacing:(CGFloat)spacing baselineAlignment:(ASBaselineLayoutBaselineAlignment)baselineAlignment justifyContent:(ASStackLayoutJustifyContent)justifyContent alignItems:(ASStackLayoutAlignItems)alignItems children:(NSArray *)children { - ASDisplayNodeAssert((style.stackLayoutStyle.direction == ASStackLayoutDirectionHorizontal && style.baselineAlignment != ASBaselineLayoutBaselineAlignmentNone) || style.stackLayoutStyle.direction == ASStackLayoutDirectionVertical, @"baselineAlignment is set to none. If you don't need baseline alignment please use ASStackLayoutSpec"); - - ASBaselineLayoutSpec *spec = [super new]; - if (spec) { - spec->_style = style; - spec->_stackChildren = std::vector>(); - for (id child in children) { - ASDisplayNodeAssert([child conformsToProtocol:@protocol(ASBaselineLayoutable)], @"child must conform to ASStackLayoutable"); - - spec->_stackChildren.push_back(child); - } + if (!(self = [super init])) { + return nil; } - return spec; + + ASDisplayNodeAssert((direction == ASStackLayoutDirectionHorizontal && baselineAlignment != ASBaselineLayoutBaselineAlignmentNone) || direction == ASStackLayoutDirectionVertical, @"baselineAlignment is set to none. If you don't need baseline alignment please use ASStackLayoutSpec"); + _direction = direction; + _alignItems = alignItems; + _spacing = spacing; + _justifyContent = justifyContent; + _baselineAlignment = baselineAlignment; + + _children = std::vector>(); + for (id child in children) { + _children.push_back(child); + } + return self; } -+ (instancetype)new + ++ (instancetype)baselineLayoutSpecWithDirection:(ASStackLayoutDirection)direction spacing:(CGFloat)spacing baselineAlignment:(ASBaselineLayoutBaselineAlignment)baselineAlignment justifyContent:(ASStackLayoutJustifyContent)justifyContent alignItems:(ASStackLayoutAlignItems)alignItems children:(NSArray *)children { - ASDISPLAYNODE_NOT_DESIGNATED_INITIALIZER(); + return [[ASBaselineLayoutSpec alloc] initWithDirection:direction spacing:spacing baselineAlignment:baselineAlignment justifyContent:justifyContent alignItems:alignItems children:children]; } - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize { - ASStackLayoutSpecStyle stackStyle = _style.stackLayoutStyle; + ASStackLayoutSpecStyle stackStyle = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems}; + ASBaselineLayoutSpecStyle style = { .baselineAlignment = _baselineAlignment, .stackLayoutStyle = stackStyle }; - const auto unpositionedLayout = ASStackUnpositionedLayout::compute(_stackChildren, stackStyle, constrainedSize); + const auto unpositionedLayout = ASStackUnpositionedLayout::compute(_children, stackStyle, constrainedSize); const auto positionedLayout = ASStackPositionedLayout::compute(unpositionedLayout, stackStyle, constrainedSize); - const auto baselinePositionedLayout = ASBaselinePositionedLayout::compute(positionedLayout, _style, constrainedSize); + const auto baselinePositionedLayout = ASBaselinePositionedLayout::compute(positionedLayout, style, constrainedSize); const CGSize finalSize = directionSize(stackStyle.direction, unpositionedLayout.stackDimensionSum, baselinePositionedLayout.crossSize); @@ -73,8 +77,21 @@ _ascender = baselinePositionedLayout.ascender; _descender = baselinePositionedLayout.descender; - return [ASLayout newWithLayoutableObject:self - size:ASSizeRangeClamp(constrainedSize, finalSize) - sublayouts:sublayouts]; + return [ASLayout layoutWithLayoutableObject:self + size:ASSizeRangeClamp(constrainedSize, finalSize) + sublayouts:sublayouts]; } + +- (void)addChild:(id)child +{ + _children.push_back(child); +} + +- (void)addChildren:(NSArray *)children +{ + for (id child in children) { + [self addChild:child]; + } +} + @end diff --git a/AsyncDisplayKit/Layout/ASBaselineStackLayoutSpec.h b/AsyncDisplayKit/Layout/ASBaselineStackLayoutSpec.h deleted file mode 100644 index 789e82f235..0000000000 --- a/AsyncDisplayKit/Layout/ASBaselineStackLayoutSpec.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - */ - -#import -#import - -typedef NS_ENUM(NSUInteger, ASBaselineStackLayoutBaselineAlignment) { - /** No baseline alignment. This is only valid for a vertical stack */ - ASBaselineStackLayoutBaselineAlignmentNone, - /** Align all children to the first baseline. This is only valid for a horizontal stack */ - ASBaselineStackLayoutBaselineAlignmentFirst, - /** Align all children to the last baseline. This is useful when a text node wraps and you want to align - to the bottom baseline. This is only valid for a horizontal stack */ - ASBaselineStackLayoutBaselineAlignmentLast, -}; - - -typedef struct { - /** Describes how the stack will be laid out */ - ASStackLayoutSpecStyle stackLayoutStyle; - - /** The type of baseline alignment */ - ASBaselineStackLayoutBaselineAlignment baselineAlignment; -} ASBaselineStackLayoutSpecStyle; - -/** - A specialized version of a stack layout that aligns its children on a baseline. This spec only works with - ASBaselineStackLayoutable children. - - If the spec is created with a horizontal direction, the children will be laid on a common baseline. - 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. -*/ -@interface ASBaselineStackLayoutSpec : ASLayoutSpec - -/** - @param style Specifies how children are laid out. - @param children ASTextLayoutable children to be positioned. - */ -+ (instancetype)newWithStyle:(ASBaselineStackLayoutSpecStyle)style children:(NSArray *)children; - -@end diff --git a/AsyncDisplayKit/Layout/ASBaselineStackLayoutSpec.mm b/AsyncDisplayKit/Layout/ASBaselineStackLayoutSpec.mm deleted file mode 100644 index bfe8a512b7..0000000000 --- a/AsyncDisplayKit/Layout/ASBaselineStackLayoutSpec.mm +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - */ - -#import "ASBaselineStackLayoutSpec.h" -#import "ASStackLayoutable.h" - -#import -#import - -#import "ASBaseDefines.h" -#import "ASInternalHelpers.h" - -#import "ASLayoutSpecUtilities.h" -#import "ASStackLayoutSpecUtilities.h" -#import "ASStackPositionedLayout.h" -#import "ASStackUnpositionedLayout.h" -#import "ASBaselineStackPositionedLayout.h" -#import "ASThread.h" - - -@implementation ASBaselineStackLayoutSpec -{ - ASBaselineStackLayoutSpecStyle _style; - std::vector> _stackChildren; - ASDN::RecursiveMutex _propertyLock; -} - -@synthesize ascender = _ascender; -@synthesize descender = _descender; - -+ (instancetype)newWithStyle:(ASBaselineStackLayoutSpecStyle)style children:(NSArray *)children -{ - ASDisplayNodeAssert((style.stackLayoutStyle.direction == ASStackLayoutDirectionHorizontal && style.baselineAlignment != ASBaselineStackLayoutBaselineAlignmentNone) || style.stackLayoutStyle.direction == ASStackLayoutDirectionVertical, @"baselineAlignment is set to none. If you don't need baseline alignment please use ASStackLayoutSpec"); - - ASBaselineStackLayoutSpec *spec = [super new]; - if (spec) { - spec->_style = style; - spec->_stackChildren = std::vector>(); - for (id child in children) { - ASDisplayNodeAssert([child conformsToProtocol:@protocol(ASBaselineStackLayoutable)], @"child must conform to ASStackLayoutable"); - - spec->_stackChildren.push_back(child); - } - } - return spec; -} - -+ (instancetype)new -{ - ASDISPLAYNODE_NOT_DESIGNATED_INITIALIZER(); -} - -- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize -{ - ASStackLayoutSpecStyle stackStyle = _style.stackLayoutStyle; - - const auto unpositionedLayout = ASStackUnpositionedLayout::compute(_stackChildren, stackStyle, constrainedSize); - const auto positionedLayout = ASStackPositionedLayout::compute(unpositionedLayout, stackStyle, constrainedSize); - const auto baselinePositionedLayout = ASBaselineStackPositionedLayout::compute(positionedLayout, _style, constrainedSize); - - const CGSize finalSize = directionSize(stackStyle.direction, unpositionedLayout.stackDimensionSum, baselinePositionedLayout.crossSize); - - NSArray *sublayouts = [NSArray arrayWithObjects:&baselinePositionedLayout.sublayouts[0] count:baselinePositionedLayout.sublayouts.size()]; - - ASDN::MutexLocker l(_propertyLock); - _ascender = baselinePositionedLayout.ascender; - _descender = baselinePositionedLayout.descender; - - return [ASLayout newWithLayoutableObject:self - size:ASSizeRangeClamp(constrainedSize, finalSize) - sublayouts:sublayouts]; -} -@end diff --git a/AsyncDisplayKit/Layout/ASBaselineStackLayoutable.h b/AsyncDisplayKit/Layout/ASBaselineStackLayoutable.h deleted file mode 100644 index 0911b93908..0000000000 --- a/AsyncDisplayKit/Layout/ASBaselineStackLayoutable.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "ASStackLayoutable.h" - -@protocol ASBaselineStackLayoutable - -/** - * @abstract The distance from the top of the layoutable object to its baseline - */ -@property (nonatomic, readwrite) CGFloat ascender; - -/** - * @abstract The distance from the bottom of the layoutable object to its baseline - */ -@property (nonatomic, readwrite) CGFloat descender; - -@end diff --git a/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h b/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h index 84e015ac57..dc50b265e7 100644 --- a/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h @@ -37,6 +37,10 @@ typedef NS_OPTIONS(NSUInteger, ASCenterLayoutSpecSizingOptions) { /** Lays out a single layoutable child and position it so that it is centered into the layout bounds. */ @interface ASCenterLayoutSpec : ASLayoutSpec +@property (nonatomic, assign) ASCenterLayoutSpecCenteringOptions centeringOptions; +@property (nonatomic, assign) ASCenterLayoutSpecSizingOptions sizingOptions; +@property (nonatomic, strong) id child; + /** * Initializer. * @@ -46,8 +50,8 @@ typedef NS_OPTIONS(NSUInteger, ASCenterLayoutSpecSizingOptions) { * * @param child The child to center. */ -+ (instancetype)newWithCenteringOptions:(ASCenterLayoutSpecCenteringOptions)centeringOptions - sizingOptions:(ASCenterLayoutSpecSizingOptions)sizingOptions - child:(id)child; ++ (instancetype)centerLayoutSpecWithCenteringOptions:(ASCenterLayoutSpecCenteringOptions)centeringOptions + sizingOptions:(ASCenterLayoutSpecSizingOptions)sizingOptions + child:(id)child; @end diff --git a/AsyncDisplayKit/Layout/ASCenterLayoutSpec.mm b/AsyncDisplayKit/Layout/ASCenterLayoutSpec.mm index f96b359172..1830895320 100644 --- a/AsyncDisplayKit/Layout/ASCenterLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASCenterLayoutSpec.mm @@ -20,22 +20,43 @@ id _child; } -+ (instancetype)newWithCenteringOptions:(ASCenterLayoutSpecCenteringOptions)centeringOptions - sizingOptions:(ASCenterLayoutSpecSizingOptions)sizingOptions - child:(id)child +- (instancetype)initWithCenteringOptions:(ASCenterLayoutSpecCenteringOptions)centeringOptions + sizingOptions:(ASCenterLayoutSpecSizingOptions)sizingOptions + child:(id)child; { - ASCenterLayoutSpec *spec = [super new]; - if (spec) { - spec->_centeringOptions = centeringOptions; - spec->_sizingOptions = sizingOptions; - spec->_child = child; + if (!(self = [super init])) { + return nil; } - return spec; + ASDisplayNodeAssertNotNil(child, @"Child cannot be nil"); + _centeringOptions = centeringOptions; + _sizingOptions = sizingOptions; + _child = child; + return self; } -+ (instancetype)new ++ (instancetype)centerLayoutSpecWithCenteringOptions:(ASCenterLayoutSpecCenteringOptions)centeringOptions + sizingOptions:(ASCenterLayoutSpecSizingOptions)sizingOptions + child:(id)child { - ASDISPLAYNODE_NOT_DESIGNATED_INITIALIZER(); + return [[self alloc] initWithCenteringOptions:centeringOptions sizingOptions:sizingOptions child:child]; +} + +- (void)setChild:(id)child +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _child = child; +} + +- (void)setCenteringOptions:(ASCenterLayoutSpecCenteringOptions)centeringOptions +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _centeringOptions = centeringOptions; +} + +- (void)setSizingOptions:(ASCenterLayoutSpecSizingOptions)sizingOptions +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _sizingOptions = sizingOptions; } - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize @@ -73,7 +94,7 @@ ASRoundPixelValue(shouldCenterAlongY ? (size.height - sublayout.size.height) * 0.5f : 0) }; - return [ASLayout newWithLayoutableObject:self size:size sublayouts:@[sublayout]]; + return [ASLayout layoutWithLayoutableObject:self size:size sublayouts:@[sublayout]]; } @end diff --git a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.h b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.h index 7f1b0c9c00..3b140dfcc7 100644 --- a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.h @@ -29,10 +29,13 @@ */ @interface ASInsetLayoutSpec : ASLayoutSpec +@property (nonatomic, strong) id child; +@property (nonatomic, assign) UIEdgeInsets insets; + /** @param insets The amount of space to inset on each side. @param child The wrapped child to inset. If nil, this method returns nil. */ -+ (instancetype)newWithInsets:(UIEdgeInsets)insets child:(id)child; ++ (instancetype)insetLayoutSpecWithInsets:(UIEdgeInsets)insets child:(id)child; @end diff --git a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm index 8db3975773..5ca96ab848 100644 --- a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm @@ -43,22 +43,32 @@ static CGFloat centerInset(CGFloat outer, CGFloat inner) @implementation ASInsetLayoutSpec -+ (instancetype)newWithInsets:(UIEdgeInsets)insets child:(id)child +- (instancetype)initWithInsets:(UIEdgeInsets)insets child:(id)child; { - if (child == nil) { + if (!(self = [super init])) { return nil; } - ASInsetLayoutSpec *spec = [super new]; - if (spec) { - spec->_insets = insets; - spec->_child = child; - } - return spec; + ASDisplayNodeAssertNotNil(child, @"Child cannot be nil"); + _insets = insets; + _child = child; + return self; } -+ (instancetype)new ++ (instancetype)insetLayoutSpecWithInsets:(UIEdgeInsets)insets child:(id)child { - ASDISPLAYNODE_NOT_DESIGNATED_INITIALIZER(); + return [[self alloc] initWithInsets:insets child:child]; +} + +- (void)setChild:(id)child +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _child = child; +} + +- (void)setInsets:(UIEdgeInsets)insets +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _insets = insets; } /** @@ -103,7 +113,7 @@ static CGFloat centerInset(CGFloat outer, CGFloat inner) sublayout.position = CGPointMake(x, y); - return [ASLayout newWithLayoutableObject:self size:computedSize sublayouts:@[sublayout]]; + return [ASLayout layoutWithLayoutableObject:self size:computedSize sublayouts:@[sublayout]]; } @end diff --git a/AsyncDisplayKit/Layout/ASLayout.h b/AsyncDisplayKit/Layout/ASLayout.h index a3d32feddc..71892b5996 100644 --- a/AsyncDisplayKit/Layout/ASLayout.h +++ b/AsyncDisplayKit/Layout/ASLayout.h @@ -43,10 +43,10 @@ extern BOOL CGPointIsNull(CGPoint point); * * @param sublayouts Sublayouts belong to the new layout. */ -+ (instancetype)newWithLayoutableObject:(id)layoutableObject - size:(CGSize)size - position:(CGPoint)position - sublayouts:(NSArray *)sublayouts; ++ (instancetype)layoutWithLayoutableObject:(id)layoutableObject + size:(CGSize)size + position:(CGPoint)position + sublayouts:(NSArray *)sublayouts; /** * Convenience initializer that has CGPointNull position. @@ -60,9 +60,9 @@ extern BOOL CGPointIsNull(CGPoint point); * * @param sublayouts Sublayouts belong to the new layout. */ -+ (instancetype)newWithLayoutableObject:(id)layoutableObject - size:(CGSize)size - sublayouts:(NSArray *)sublayouts; ++ (instancetype)layoutWithLayoutableObject:(id)layoutableObject + size:(CGSize)size + sublayouts:(NSArray *)sublayouts; /** * Convenience that has CGPointNull position and no sublayouts. @@ -73,7 +73,7 @@ extern BOOL CGPointIsNull(CGPoint point); * * @param size The size of this layout. */ -+ (instancetype)newWithLayoutableObject:(id)layoutableObject size:(CGSize)size; ++ (instancetype)layoutWithLayoutableObject:(id)layoutableObject size:(CGSize)size; /** diff --git a/AsyncDisplayKit/Layout/ASLayout.mm b/AsyncDisplayKit/Layout/ASLayout.mm index 31dd8ebc27..6695a07bde 100644 --- a/AsyncDisplayKit/Layout/ASLayout.mm +++ b/AsyncDisplayKit/Layout/ASLayout.mm @@ -22,10 +22,10 @@ extern BOOL CGPointIsNull(CGPoint point) @implementation ASLayout -+ (instancetype)newWithLayoutableObject:(id)layoutableObject - size:(CGSize)size - position:(CGPoint)position - sublayouts:(NSArray *)sublayouts ++ (instancetype)layoutWithLayoutableObject:(id)layoutableObject + size:(CGSize)size + position:(CGPoint)position + sublayouts:(NSArray *)sublayouts { ASDisplayNodeAssert(layoutableObject, @"layoutableObject is required."); for (ASLayout *sublayout in sublayouts) { @@ -42,16 +42,16 @@ extern BOOL CGPointIsNull(CGPoint point) return l; } -+ (instancetype)newWithLayoutableObject:(id)layoutableObject - size:(CGSize)size - sublayouts:(NSArray *)sublayouts ++ (instancetype)layoutWithLayoutableObject:(id)layoutableObject + size:(CGSize)size + sublayouts:(NSArray *)sublayouts { - return [self newWithLayoutableObject:layoutableObject size:size position:CGPointNull sublayouts:sublayouts]; + return [self layoutWithLayoutableObject:layoutableObject size:size position:CGPointNull sublayouts:sublayouts]; } -+ (instancetype)newWithLayoutableObject:(id)layoutableObject size:(CGSize)size ++ (instancetype)layoutWithLayoutableObject:(id)layoutableObject size:(CGSize)size { - return [self newWithLayoutableObject:layoutableObject size:size sublayouts:nil]; + return [self layoutWithLayoutableObject:layoutableObject size:size sublayouts:nil]; } - (ASLayout *)flattenedLayoutUsingPredicateBlock:(BOOL (^)(ASLayout *))predicateBlock @@ -76,10 +76,10 @@ extern BOOL CGPointIsNull(CGPoint point) context.visited = YES; if (predicateBlock(context.layout)) { - [flattenedSublayouts addObject:[ASLayout newWithLayoutableObject:context.layout.layoutableObject - size:context.layout.size - position:context.absolutePosition - sublayouts:nil]]; + [flattenedSublayouts addObject:[ASLayout layoutWithLayoutableObject:context.layout.layoutableObject + size:context.layout.size + position:context.absolutePosition + sublayouts:nil]]; } for (ASLayout *sublayout in context.layout.sublayouts) { @@ -88,7 +88,7 @@ extern BOOL CGPointIsNull(CGPoint point) } } - return [ASLayout newWithLayoutableObject:_layoutableObject size:_size sublayouts:flattenedSublayouts]; + return [ASLayout layoutWithLayoutableObject:_layoutableObject size:_size sublayouts:flattenedSublayouts]; } @end diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.h b/AsyncDisplayKit/Layout/ASLayoutSpec.h index e92bbf75cc..bb200cbfe1 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.h @@ -13,4 +13,13 @@ /** A layout spec is an immutable object that describes a layout, loosely inspired by React. */ @interface ASLayoutSpec : NSObject +/** + Creation of a layout spec should only happen by a user in layoutSpecThatFits:. During that method, a + layout spec can be created and mutated. Once it is passed back to ASDK, the isMutable flag will be + set to NO and any further mutations will cause an assert. + */ +@property (nonatomic, assign) BOOL isMutable; + +- (instancetype)init; + @end diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index 8b3efd6f4d..ef09aa365e 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -25,20 +25,21 @@ @synthesize flexBasis = _flexBasis; @synthesize alignSelf = _alignSelf; -+ (instancetype)new +- (instancetype)init { - ASLayoutSpec *spec = [super new]; - if (spec) { - spec->_flexBasis = ASRelativeDimensionUnconstrained; + if (!(self = [super init])) { + return nil; } - return spec; + _flexBasis = ASRelativeDimensionUnconstrained; + _isMutable = YES; + return self; } #pragma mark - Layout - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize { - return [ASLayout newWithLayoutableObject:self size:constrainedSize.min]; + return [ASLayout layoutWithLayoutableObject:self size:constrainedSize.min]; } @end diff --git a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.h b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.h index 846b0cece5..35a9577dde 100644 --- a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.h @@ -15,6 +15,9 @@ */ @interface ASOverlayLayoutSpec : ASLayoutSpec -+ (instancetype)newWithChild:(id)child overlay:(id)overlay; +@property (nonatomic, strong) id child; +@property (nonatomic, strong) id overlay; + ++ (instancetype)overlayLayoutSpecWithChild:(id)child overlay:(id)overlay; @end diff --git a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm index b478f69971..f4f025573b 100644 --- a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm @@ -20,20 +20,32 @@ id _child; } -+ (instancetype)newWithChild:(id)child overlay:(id)overlay +- (instancetype)initWithChild:(id)child overlay:(id)overlay { - ASOverlayLayoutSpec *spec = [super new]; - if (spec) { - ASDisplayNodeAssertNotNil(child, @"Child that will be overlayed on shouldn't be nil"); - spec->_overlay = overlay; - spec->_child = child; + if (!(self = [super init])) { + return nil; } - return spec; + ASDisplayNodeAssertNotNil(child, @"Child that will be overlayed on shouldn't be nil"); + _overlay = overlay; + _child = child; + return self; } -+ (instancetype)new ++ (instancetype)overlayLayoutSpecWithChild:(id)child overlay:(id)overlay { - ASDISPLAYNODE_NOT_DESIGNATED_INITIALIZER(); + return [[self alloc] initWithChild:child overlay:overlay]; +} + +- (void)setChild:(id)child +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _child = child; +} + +- (void)setOverlay:(id)overlay +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _overlay = overlay; } /** @@ -50,7 +62,7 @@ [sublayouts addObject:overlayLayout]; } - return [ASLayout newWithLayoutableObject:self size:contentsLayout.size sublayouts:sublayouts]; + return [ASLayout layoutWithLayoutableObject:self size:contentsLayout.size sublayouts:sublayouts]; } @end diff --git a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.h b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.h index 73be620d71..fd7f6d657b 100644 --- a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.h @@ -31,6 +31,10 @@ **/ @interface ASRatioLayoutSpec : ASLayoutSpec -+ (instancetype)newWithRatio:(CGFloat)ratio child:(id)child; + +@property (nonatomic, strong) id child; +@property (nonatomic, assign) CGFloat ratio; + ++ (instancetype)ratioLayoutSpecWithRatio:(CGFloat)ratio child:(id)child; @end diff --git a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm index 2e358b533f..5e5c6f0c66 100644 --- a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm @@ -25,24 +25,33 @@ id _child; } -+ (instancetype)newWithRatio:(CGFloat)ratio child:(id)child ++ (instancetype)ratioLayoutSpecWithRatio:(CGFloat)ratio child:(id)child { - ASDisplayNodeAssert(ratio > 0, @"Ratio should be strictly positive, but received %f", ratio); - if (child == nil) { - return nil; - } - - ASRatioLayoutSpec *spec = [super new]; - if (spec) { - spec->_ratio = ratio; - spec->_child = child; - } - return spec; + return [[self alloc] initWithRatio:ratio child:child]; } -+ (instancetype)new +- (instancetype)initWithRatio:(CGFloat)ratio child:(id)child; { - ASDISPLAYNODE_NOT_DESIGNATED_INITIALIZER(); + if (!(self = [super init])) { + return nil; + } + ASDisplayNodeAssertNotNil(child, @"Child cannot be nil"); + ASDisplayNodeAssert(ratio > 0, @"Ratio should be strictly positive, but received %f", ratio); + _ratio = ratio; + _child = child; + return self; +} + +- (void)setChild:(id)child +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _child = child; +} + +- (void)setRatio:(CGFloat)ratio +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _ratio = ratio; } - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize @@ -70,7 +79,7 @@ const ASSizeRange childRange = (bestSize == sizeOptions.end()) ? constrainedSize : ASSizeRangeMake(*bestSize, *bestSize); ASLayout *sublayout = [_child measureWithSizeRange:childRange]; sublayout.position = CGPointZero; - return [ASLayout newWithLayoutableObject:self size:sublayout.size sublayouts:@[sublayout]]; + return [ASLayout layoutWithLayoutableObject:self size:sublayout.size sublayouts:@[sublayout]]; } @end diff --git a/AsyncDisplayKit/Layout/ASStackLayoutSpec.h b/AsyncDisplayKit/Layout/ASStackLayoutSpec.h index 6a3e999db5..7825a9b8fc 100644 --- a/AsyncDisplayKit/Layout/ASStackLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASStackLayoutSpec.h @@ -11,16 +11,6 @@ #import #import -typedef struct { - /** Specifies the direction children are stacked in. */ - ASStackLayoutDirection direction; - /** The amount of space between each child. */ - CGFloat spacing; - /** How children are aligned if there are no flexible children. */ - ASStackLayoutJustifyContent justifyContent; - /** Orientation of children along cross axis */ - ASStackLayoutAlignItems alignItems; -} ASStackLayoutSpecStyle; /** A simple layout spec that stacks a list of children vertically or horizontally. @@ -45,10 +35,27 @@ typedef struct { */ @interface ASStackLayoutSpec : ASLayoutSpec +/** Specifies the direction children are stacked in. */ +@property (nonatomic, assign) ASStackLayoutDirection direction; +/** The amount of space between each child. */ +@property (nonatomic, assign) CGFloat spacing; +/** The amount of space between each child. */ +@property (nonatomic, assign) ASStackLayoutJustifyContent justifyContent; +/** Orientation of children along cross axis */ +@property (nonatomic, assign) ASStackLayoutAlignItems alignItems; + +- (instancetype)init; + /** - @param style Specifies how children are laid out. + @param direction The direction of the stack view (horizontal or vertical) + @param spacing The spacing between the children + @param justifyContent If no children are flexible, this describes how to fill any extra space + @param alignItems Orientation of the children along the cross axis @param children ASLayoutable children to be positioned. */ -+ (instancetype)newWithStyle:(ASStackLayoutSpecStyle)style children:(NSArray *)children; ++ (instancetype)stackLayoutSpecWithDirection:(ASStackLayoutDirection)direction spacing:(CGFloat)spacing justifyContent:(ASStackLayoutJustifyContent)justifyContent alignItems:(ASStackLayoutAlignItems)alignItems children:(NSArray *)children; + +- (void)addChild:(id)child; +- (void)addChildren:(NSArray *)children; @end diff --git a/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm b/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm index c5c3660fc4..3149979dd6 100644 --- a/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm @@ -24,40 +24,83 @@ @implementation ASStackLayoutSpec { - ASStackLayoutSpecStyle _style; std::vector> _children; } -+ (instancetype)newWithStyle:(ASStackLayoutSpecStyle)style children:(NSArray *)children +- (instancetype)init { - ASStackLayoutSpec *spec = [super new]; - if (spec) { - spec->_style = style; - spec->_children = std::vector>(); - for (id child in children) { - ASDisplayNodeAssert([child conformsToProtocol:@protocol(ASStackLayoutable)], @"child must conform to ASStackLayoutable"); - - spec->_children.push_back(child); - } - } - return spec; + return [self initWithDirection:ASStackLayoutDirectionHorizontal spacing:0.0 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsStart children:nil]; } -+ (instancetype)new ++ (instancetype)stackLayoutSpecWithDirection:(ASStackLayoutDirection)direction spacing:(CGFloat)spacing justifyContent:(ASStackLayoutJustifyContent)justifyContent alignItems:(ASStackLayoutAlignItems)alignItems children:(NSArray *)children { - ASDISPLAYNODE_NOT_DESIGNATED_INITIALIZER(); + return [[self alloc] initWithDirection:direction spacing:spacing justifyContent:justifyContent alignItems:alignItems children:children]; +} + +- (instancetype)initWithDirection:(ASStackLayoutDirection)direction spacing:(CGFloat)spacing justifyContent:(ASStackLayoutJustifyContent)justifyContent alignItems:(ASStackLayoutAlignItems)alignItems children:(NSArray *)children +{ + if (!(self = [super init])) { + return nil; + } + _direction = direction; + _alignItems = alignItems; + _spacing = spacing; + _justifyContent = justifyContent; + + _children = std::vector>(); + for (id child in children) { + _children.push_back(child); + } + return self; +} + +- (void)addChild:(id)child +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _children.push_back(child); +} + +- (void)addChildren:(NSArray *)children +{ + for (id child in children) { + [self addChild:child]; + } +} + +- (void)setDirection:(ASStackLayoutDirection)direction +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _direction = direction; +} + +- (void)setAlignItems:(ASStackLayoutAlignItems)alignItems +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _alignItems = alignItems; +} + +- (void)setJustifyContent:(ASStackLayoutJustifyContent)justifyContent +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _justifyContent = justifyContent; +} + +- (void)setSpacing:(CGFloat)spacing +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _spacing = spacing; } - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize { - const auto unpositionedLayout = ASStackUnpositionedLayout::compute(_children, _style, constrainedSize); - const auto positionedLayout = ASStackPositionedLayout::compute(unpositionedLayout, _style, constrainedSize); - const CGSize finalSize = directionSize(_style.direction, unpositionedLayout.stackDimensionSum, positionedLayout.crossSize); + ASStackLayoutSpecStyle style = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems}; + const auto unpositionedLayout = ASStackUnpositionedLayout::compute(_children, style, constrainedSize); + const auto positionedLayout = ASStackPositionedLayout::compute(unpositionedLayout, style, constrainedSize); + const CGSize finalSize = directionSize(style.direction, unpositionedLayout.stackDimensionSum, positionedLayout.crossSize); NSArray *sublayouts = [NSArray arrayWithObjects:&positionedLayout.sublayouts[0] count:positionedLayout.sublayouts.size()]; - - return [ASLayout newWithLayoutableObject:self - size:ASSizeRangeClamp(constrainedSize, finalSize) - sublayouts:sublayouts]; + return [ASLayout layoutWithLayoutableObject:self + size:ASSizeRangeClamp(constrainedSize, finalSize) + sublayouts:sublayouts]; } @end diff --git a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.h b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.h index 259c32c4d6..38ed2f06d6 100644 --- a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.h @@ -34,7 +34,7 @@ * * @param size The size range that this child's size is trstricted according to. */ -+ (instancetype)newWithPosition:(CGPoint)position layoutableObject:(id)layoutableObject size:(ASRelativeSizeRange)size; ++ (instancetype)staticLayoutChildWithPosition:(CGPoint)position layoutableObject:(id)layoutableObject size:(ASRelativeSizeRange)size; /** * Convenience initializer with default size is Unconstrained in both dimensions, which sets the child's min size to zero @@ -44,7 +44,7 @@ * * @param layoutableObject The backing ASLayoutable object of this child. */ -+ (instancetype)newWithPosition:(CGPoint)position layoutableObject:(id)layoutableObject; ++ (instancetype)staticLayoutChildWithPosition:(CGPoint)position layoutableObject:(id)layoutableObject; @end @@ -58,6 +58,8 @@ /** @param children Children to be positioned at fixed positions, each is of type ASStaticLayoutSpecChild. */ -+ (instancetype)newWithChildren:(NSArray *)children; ++ (instancetype)staticLayoutSpecWithChildren:(NSArray *)children; + +- (void)addChild:(ASStaticLayoutSpecChild *)child; @end diff --git a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm index 1610ab0db3..61a6d1724e 100644 --- a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm @@ -16,9 +16,9 @@ @implementation ASStaticLayoutSpecChild -+ (instancetype)newWithPosition:(CGPoint)position layoutableObject:(id)layoutableObject size:(ASRelativeSizeRange)size ++ (instancetype)staticLayoutChildWithPosition:(CGPoint)position layoutableObject:(id)layoutableObject size:(ASRelativeSizeRange)size; { - ASStaticLayoutSpecChild *c = [super new]; + ASStaticLayoutSpecChild *c = [[super alloc] init]; if (c) { c->_position = position; c->_layoutableObject = layoutableObject; @@ -27,9 +27,9 @@ return c; } -+ (instancetype)newWithPosition:(CGPoint)position layoutableObject:(id)layoutableObject ++ (instancetype)staticLayoutChildWithPosition:(CGPoint)position layoutableObject:(id)layoutableObject { - return [self newWithPosition:position layoutableObject:layoutableObject size:ASRelativeSizeRangeUnconstrained]; + return [self staticLayoutChildWithPosition:position layoutableObject:layoutableObject size:ASRelativeSizeRangeUnconstrained]; } @end @@ -39,18 +39,24 @@ NSArray *_children; } -+ (instancetype)newWithChildren:(NSArray *)children ++ (instancetype)staticLayoutSpecWithChildren:(NSArray *)children { - ASStaticLayoutSpec *spec = [super new]; - if (spec) { - spec->_children = children; - } - return spec; + return [[self alloc] initWithChildren:children]; } -+ (instancetype)new +- (instancetype)initWithChildren:(NSArray *)children { - ASDISPLAYNODE_NOT_DESIGNATED_INITIALIZER(); + if (!(self = [super init])) { + return nil; + } + _children = children; + return self; +} + +- (void)addChild:(ASStaticLayoutSpecChild *)child +{ + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + _children = [_children arrayByAddingObject:child]; } - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize @@ -88,9 +94,9 @@ } } - return [ASLayout newWithLayoutableObject:self - size:ASSizeRangeClamp(constrainedSize, size) - sublayouts:sublayouts]; + return [ASLayout layoutWithLayoutableObject:self + size:ASSizeRangeClamp(constrainedSize, size) + sublayouts:sublayouts]; } @end diff --git a/AsyncDisplayKit/Private/ASBaselinePositionedLayout.h b/AsyncDisplayKit/Private/ASBaselinePositionedLayout.h index 4f023cd5f4..e3857d5ed4 100644 --- a/AsyncDisplayKit/Private/ASBaselinePositionedLayout.h +++ b/AsyncDisplayKit/Private/ASBaselinePositionedLayout.h @@ -13,6 +13,14 @@ #import "ASBaselineLayoutSpec.h" #import "ASStackPositionedLayout.h" +typedef struct { + /** Describes how the stack will be laid out */ + ASStackLayoutSpecStyle stackLayoutStyle; + + /** The type of baseline alignment */ + ASBaselineLayoutBaselineAlignment baselineAlignment; +} ASBaselineLayoutSpecStyle; + struct ASBaselinePositionedLayout { const std::vector sublayouts; const CGFloat crossSize; diff --git a/AsyncDisplayKit/Private/ASBaselineStackPositionedLayout.h b/AsyncDisplayKit/Private/ASBaselineStackPositionedLayout.h deleted file mode 100644 index 8f18216a98..0000000000 --- a/AsyncDisplayKit/Private/ASBaselineStackPositionedLayout.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - */ - -#import "ASLayout.h" -#import "ASDimension.h" -#import "ASBaselineStackLayoutSpec.h" -#import "ASStackPositionedLayout.h" - -struct ASBaselineStackPositionedLayout { - const std::vector sublayouts; - const CGFloat crossSize; - const CGFloat ascender; - const CGFloat descender; - - /** Given a positioned layout, computes each child position using baseline alignment. */ - static ASBaselineStackPositionedLayout compute(const ASStackPositionedLayout &positionedLayout, - const ASBaselineStackLayoutSpecStyle &style, - const ASSizeRange &constrainedSize); -}; diff --git a/AsyncDisplayKit/Private/ASBaselineStackPositionedLayout.mm b/AsyncDisplayKit/Private/ASBaselineStackPositionedLayout.mm deleted file mode 100644 index 042f8479df..0000000000 --- a/AsyncDisplayKit/Private/ASBaselineStackPositionedLayout.mm +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - */ - -#import "ASBaselineStackPositionedLayout.h" - -#import "ASLayoutSpecUtilities.h" -#import "ASStackLayoutSpecUtilities.h" - -static CGFloat baselineForItem(const ASBaselineStackLayoutSpecStyle &style, - const ASLayout *layout) { - - __weak id child = (id) layout.layoutableObject; - switch (style.baselineAlignment) { - case ASBaselineStackLayoutBaselineAlignmentNone: - return 0; - case ASBaselineStackLayoutBaselineAlignmentFirst: - return child.ascender; - case ASBaselineStackLayoutBaselineAlignmentLast: - return layout.size.height + child.descender; - } - -} - -static CGFloat baselineOffset(const ASBaselineStackLayoutSpecStyle &style, - const ASLayout *l, - const CGFloat maxAscender, - const CGFloat maxBaseline) -{ - if (style.stackLayoutStyle.direction == ASStackLayoutDirectionHorizontal) { - __weak id child = (id)l.layoutableObject; - switch (style.baselineAlignment) { - case ASBaselineStackLayoutBaselineAlignmentFirst: - return maxAscender - child.ascender; - case ASBaselineStackLayoutBaselineAlignmentLast: - return maxBaseline - baselineForItem(style, l); - case ASBaselineStackLayoutBaselineAlignmentNone: - return 0; - } - } - return 0; -} - -static CGFloat maxDimensionForLayout(const ASLayout *l, - const ASStackLayoutSpecStyle &style) -{ - CGFloat maxDimension = crossDimension(style.direction, l.size); - style.direction == ASStackLayoutDirectionVertical ? maxDimension += l.position.x : maxDimension += l.position.y; - return maxDimension; -} - -ASBaselineStackPositionedLayout ASBaselineStackPositionedLayout::compute(const ASStackPositionedLayout &positionedLayout, - const ASBaselineStackLayoutSpecStyle &style, - const ASSizeRange &constrainedSize) -{ - ASStackLayoutSpecStyle stackStyle = style.stackLayoutStyle; - - /* Step 1: Look at each child and determine the distance from the top of the child node it's baseline. - For example, let's say we have the following two text nodes and want to align them to the first baseline: - - Hello! Why, hello there! How - are you today? - - The first node has a font of size 14, the second a font of size 12. The first node will have a baseline offset of - the ascender of a font of size 14, the second will have a baseline of the ascender of a font of size 12. The first - baseline will be larger so we will keep that as the max baseline. - - However, if were to align from the last baseline we'd find the max baseline by taking the height of node and adding - the font's descender (its negative). In the case of the first node, which is only 1 line, this should be the same value as the ascender. - The second node, however, has a larger height and there will have a larger baseline offset. - */ - const auto baselineIt = std::max_element(positionedLayout.sublayouts.begin(), positionedLayout.sublayouts.end(), [&](const ASLayout *a, const ASLayout *b){ - return baselineForItem(style, a) < baselineForItem(style, b); - }); - const CGFloat maxBaseline = baselineIt == positionedLayout.sublayouts.end() ? 0 : baselineForItem(style, *baselineIt); - - /* - Step 2: Find the max ascender for all of the children. - Imagine 3 nodes aligned horizontally, all with the same text but with font sizes of 12, 14, 16. Because it is has the largest - ascender node with font size of 16 will not need to move, the other two nodes will align to this node's baseline. The offset we will use - for each node is our computed maxAscender - node.ascender. If the 16pt node had an ascender of 10 and the 14pt node - had an ascender of 8, that means we will offset the 14pt node by 2 pts. - - Note: if we are alinging to the last baseline, then we don't need this value in our computation. However, we do want - 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){ - return ((id)a.layoutableObject).ascender < ((id)b.layoutableObject).ascender; - }); - const CGFloat maxAscender = baselineIt == positionedLayout.sublayouts.end() ? 0 : ((id)(*ascenderIt).layoutableObject).ascender; - - /* - Step 3: Take each child and update its layout position based on the baseline offset. - - If this is a horizontal stack, we take a positioned child and add to its y offset to align it to the maxBaseline of the children. - If this is a vertical stack, we add the child's descender to the location of the next child to position. This will ensure the - spacing between the two nodes is from the baseline, not the bounding box. - - */ - CGPoint p = CGPointZero; - BOOL first = YES; - auto stackedChildren = AS::map(positionedLayout.sublayouts, [&](ASLayout *l) -> ASLayout *{ - __weak id child = (id) l.layoutableObject; - p = p + directionPoint(stackStyle.direction, child.spacingBefore, 0); - if (first) { - // if this is the first item use the previously computed start point - p = l.position; - } else { - // otherwise add the stack spacing - p = p + directionPoint(stackStyle.direction, stackStyle.spacing, 0); - } - first = NO; - - // Find the difference between this node's baseline and the max baseline of all the children. Add this difference to the child's y position. - l.position = p + CGPointMake(0, baselineOffset(style, l, maxAscender, maxBaseline)); - - // If we are a vertical stack, add the item's descender (it is negative) to the offset for the next node. This will ensure we are spacing - // node from baselines and not bounding boxes. - CGFloat spacingAfterBaseline = 0; - if (stackStyle.direction == ASStackLayoutDirectionVertical) { - spacingAfterBaseline = child.descender; - } - p = p + directionPoint(stackStyle.direction, stackDimension(stackStyle.direction, l.size) + child.spacingAfter + spacingAfterBaseline, 0); - - return l; - }); - - /* - Step 4: Since we have been mucking with positions, there is a chance that our cross size has changed. Imagine a node with a font size of 40 - and another node with a font size of 12 but with multiple lines. We align these nodes to the first baseline, which will be the baseline of the node with - font size of 40 (max ascender). Now, we have to move the node with multiple lines down to the other node's baseline. This node with multiple lines will - extend below the first node farther than it did before aligning the baselines thus increasing the cross size. - - After finding the new cross size, we need to clamp it so that it fits within the constrainted size. - - */ - const auto it = std::max_element(stackedChildren.begin(), stackedChildren.end(), - [&](ASLayout *a, ASLayout *b) { - return maxDimensionForLayout(a, stackStyle) < maxDimensionForLayout(b, stackStyle); - }); - const auto largestChildCrossSize = it == stackedChildren.end() ? 0 : maxDimensionForLayout(*it, stackStyle); - const auto minCrossSize = crossDimension(stackStyle.direction, constrainedSize.min); - const auto maxCrossSize = crossDimension(stackStyle.direction, constrainedSize.max); - const CGFloat crossSize = MIN(MAX(minCrossSize, largestChildCrossSize), maxCrossSize); - - /* - 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. - */ - 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; - }); - const CGFloat minDescender = descenderIt == stackedChildren.end() ? 0 : ((id)(*descenderIt).layoutableObject).descender; - - return {stackedChildren, crossSize, maxAscender, minDescender}; -} diff --git a/AsyncDisplayKit/Private/ASStackLayoutSpecUtilities.h b/AsyncDisplayKit/Private/ASStackLayoutSpecUtilities.h index 4f5eff0aeb..33895b9bd5 100644 --- a/AsyncDisplayKit/Private/ASStackLayoutSpecUtilities.h +++ b/AsyncDisplayKit/Private/ASStackLayoutSpecUtilities.h @@ -10,6 +10,13 @@ #import "ASStackLayoutSpec.h" +typedef struct { + ASStackLayoutDirection direction; + CGFloat spacing; + ASStackLayoutJustifyContent justifyContent; + ASStackLayoutAlignItems alignItems; +} ASStackLayoutSpecStyle; + inline CGFloat stackDimension(const ASStackLayoutDirection direction, const CGSize size) { return (direction == ASStackLayoutDirectionVertical) ? size.height : size.width; diff --git a/AsyncDisplayKit/Private/ASStackUnpositionedLayout.h b/AsyncDisplayKit/Private/ASStackUnpositionedLayout.h index 44b7770ccf..93a2efcb20 100644 --- a/AsyncDisplayKit/Private/ASStackUnpositionedLayout.h +++ b/AsyncDisplayKit/Private/ASStackUnpositionedLayout.h @@ -11,6 +11,7 @@ #import #import "ASLayout.h" +#import "ASStackLayoutSpecUtilities.h" #import "ASStackLayoutSpec.h" struct ASStackUnpositionedItem { diff --git a/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm b/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm index 0c094bedfd..cc3be53d1c 100644 --- a/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm +++ b/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm @@ -297,7 +297,7 @@ static std::vector layoutChildrenAlongUnconstrainedStac const CGFloat exactStackDimension = ASRelativeDimensionResolve(child.flexBasis, stackDimension(style.direction, size)); if (useOptimizedFlexing && isFlexibleInBothDirections(child)) { - return { child, [ASLayout newWithLayoutableObject:child size:{0, 0}] }; + return { child, [ASLayout layoutWithLayoutableObject:child size:{0, 0}] }; } else { return { child, diff --git a/AsyncDisplayKitTests/ASCenterLayoutSpecSnapshotTests.mm b/AsyncDisplayKitTests/ASCenterLayoutSpecSnapshotTests.mm index 388e7d0e7e..5a7cbd0a92 100644 --- a/AsyncDisplayKitTests/ASCenterLayoutSpecSnapshotTests.mm +++ b/AsyncDisplayKitTests/ASCenterLayoutSpecSnapshotTests.mm @@ -52,9 +52,9 @@ static const ASSizeRange kSize = {{100, 120}, {320, 160}}; ASLayoutSpec *layoutSpec = [ASBackgroundLayoutSpec - newWithChild: + backgroundLayoutSpecWithChild: [ASCenterLayoutSpec - newWithCenteringOptions:options + centerLayoutSpecWithCenteringOptions:options sizingOptions:sizingOptions child:foregroundNode] background:backgroundNode]; @@ -98,11 +98,11 @@ static NSString *suffixForCenteringOptions(ASCenterLayoutSpecCenteringOptions ce ASCenterLayoutSpec *layoutSpec = [ASCenterLayoutSpec - newWithCenteringOptions:ASCenterLayoutSpecCenteringNone + centerLayoutSpecWithCenteringOptions:ASCenterLayoutSpecCenteringNone sizingOptions:{} child: [ASBackgroundLayoutSpec - newWithChild:[ASStackLayoutSpec newWithStyle:{} children:@[foregroundNode]] + backgroundLayoutSpecWithChild:[ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical spacing:0 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsStart children:@[foregroundNode]] background:backgroundNode]]; [self testLayoutSpec:layoutSpec sizeRange:kSize subnodes:@[backgroundNode, foregroundNode] identifier:nil]; diff --git a/AsyncDisplayKitTests/ASInsetLayoutSpecSnapshotTests.mm b/AsyncDisplayKitTests/ASInsetLayoutSpecSnapshotTests.mm index 9ff4bf219e..994acee8c4 100644 --- a/AsyncDisplayKitTests/ASInsetLayoutSpecSnapshotTests.mm +++ b/AsyncDisplayKitTests/ASInsetLayoutSpecSnapshotTests.mm @@ -61,7 +61,7 @@ static NSString *nameForInsets(UIEdgeInsets insets) ASLayoutSpec *layoutSpec = [ASBackgroundLayoutSpec - newWithChild:[ASInsetLayoutSpec newWithInsets:insets child:foregroundNode] + backgroundLayoutSpecWithChild:[ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:foregroundNode] background:backgroundNode]; static ASSizeRange kVariableSize = {{0, 0}, {300, 300}}; @@ -82,7 +82,7 @@ static NSString *nameForInsets(UIEdgeInsets insets) ASLayoutSpec *layoutSpec = [ASBackgroundLayoutSpec - newWithChild:[ASInsetLayoutSpec newWithInsets:insets child:foregroundNode] + backgroundLayoutSpecWithChild:[ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:foregroundNode] background:backgroundNode]; static ASSizeRange kFixedSize = {{300, 300}, {300, 300}}; @@ -104,7 +104,7 @@ static NSString *nameForInsets(UIEdgeInsets insets) ASLayoutSpec *layoutSpec = [ASBackgroundLayoutSpec - newWithChild:[ASInsetLayoutSpec newWithInsets:insets child:foregroundNode] + backgroundLayoutSpecWithChild:[ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:foregroundNode] background:backgroundNode]; static ASSizeRange kFixedSize = {{300, 300}, {300, 300}}; diff --git a/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m b/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m index 0141d225e6..4cd9232f05 100644 --- a/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m +++ b/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m @@ -55,7 +55,7 @@ { ASLayout *layout = [layoutSpecUnderTest measureWithSizeRange:sizeRange]; layout.position = CGPointZero; - layout = [ASLayout newWithLayoutableObject:self size:layout.size sublayouts:@[layout]]; + layout = [ASLayout layoutWithLayoutableObject:self size:layout.size sublayouts:@[layout]]; _layoutUnderTest = [layout flattenedLayoutUsingPredicateBlock:^BOOL(ASLayout *evaluatedLayout) { return [self.subnodes containsObject:evaluatedLayout.layoutableObject]; }]; diff --git a/AsyncDisplayKitTests/ASOverlayLayoutSpecSnapshotTests.mm b/AsyncDisplayKitTests/ASOverlayLayoutSpecSnapshotTests.mm index 066a6c47b5..f024de9faa 100644 --- a/AsyncDisplayKitTests/ASOverlayLayoutSpecSnapshotTests.mm +++ b/AsyncDisplayKitTests/ASOverlayLayoutSpecSnapshotTests.mm @@ -34,10 +34,10 @@ static const ASSizeRange kSize = {{320, 320}, {320, 320}}; ASLayoutSpec *layoutSpec = [ASOverlayLayoutSpec - newWithChild:backgroundNode + overlayLayoutSpecWithChild:backgroundNode overlay: [ASCenterLayoutSpec - newWithCenteringOptions:ASCenterLayoutSpecCenteringXY + centerLayoutSpecWithCenteringOptions:ASCenterLayoutSpecCenteringXY sizingOptions:{} child:foregroundNode]]; diff --git a/AsyncDisplayKitTests/ASRatioLayoutSpecSnapshotTests.mm b/AsyncDisplayKitTests/ASRatioLayoutSpecSnapshotTests.mm index ffe30e0f0d..5345a84649 100644 --- a/AsyncDisplayKitTests/ASRatioLayoutSpecSnapshotTests.mm +++ b/AsyncDisplayKitTests/ASRatioLayoutSpecSnapshotTests.mm @@ -30,7 +30,7 @@ static const ASSizeRange kFixedSize = {{0, 0}, {100, 100}}; ASStaticSizeDisplayNode *subnode = ASDisplayNodeWithBackgroundColor([UIColor greenColor]); subnode.staticSize = childSize; - ASLayoutSpec *layoutSpec = [ASRatioLayoutSpec newWithRatio:ratio child:subnode]; + ASLayoutSpec *layoutSpec = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:ratio child:subnode]; [self testLayoutSpec:layoutSpec sizeRange:kFixedSize subnodes:@[subnode] identifier:identifier]; } diff --git a/AsyncDisplayKitTests/ASStackLayoutSpecSnapshotTests.mm b/AsyncDisplayKitTests/ASStackLayoutSpecSnapshotTests.mm index 21a885444e..9b6c3d655d 100644 --- a/AsyncDisplayKitTests/ASStackLayoutSpecSnapshotTests.mm +++ b/AsyncDisplayKitTests/ASStackLayoutSpecSnapshotTests.mm @@ -11,6 +11,7 @@ #import "ASLayoutSpecSnapshotTestsHelper.h" #import "ASStackLayoutSpec.h" +#import "ASStackLayoutSpecUtilities.h" #import "ASBackgroundLayoutSpec.h" #import "ASRatioLayoutSpec.h" #import "ASInsetLayoutSpec.h" @@ -79,7 +80,7 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex) ASLayoutSpec *layoutSpec = [ASBackgroundLayoutSpec - newWithChild:[ASStackLayoutSpec newWithStyle:style children:children] + backgroundLayoutSpecWithChild:[ASStackLayoutSpec stackLayoutSpecWithDirection:style.direction spacing:style.spacing justifyContent:style.justifyContent alignItems:style.alignItems children:children] background:backgroundNode]; NSMutableArray *newSubnodes = [NSMutableArray arrayWithObject:backgroundNode]; @@ -179,17 +180,12 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex) ASLayoutSpec *layoutSpec = [ASInsetLayoutSpec - newWithInsets:{10, 10, 10 ,10} + insetLayoutSpecWithInsets:{10, 10, 10 ,10} child: [ASBackgroundLayoutSpec - newWithChild: + backgroundLayoutSpecWithChild: [ASStackLayoutSpec - newWithStyle:{ - .direction = ASStackLayoutDirectionVertical, - .spacing = 10, - .alignItems = ASStackLayoutAlignItemsStretch - } - children:@[]] + stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical spacing:10 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsStretch children:@[]] background:backgroundNode]]; // width 300px; height 0-300px @@ -257,7 +253,7 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex) ASStaticSizeDisplayNode * subnode2 = ASDisplayNodeWithBackgroundColor([UIColor redColor]); subnode2.staticSize = {50, 50}; - ASRatioLayoutSpec *child1 = [ASRatioLayoutSpec newWithRatio:1.5 child:subnode1]; + ASRatioLayoutSpec *child1 = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.5 child:subnode1]; child1.flexBasis = ASRelativeDimensionMakeWithPercent(1); child1.flexGrow = YES; child1.flexShrink = YES; @@ -481,7 +477,7 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex) ((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {10, 0}; ((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {3000, 3000}; - ASRatioLayoutSpec *child2 = [ASRatioLayoutSpec newWithRatio:1.0 child:subnodes[2]]; + ASRatioLayoutSpec *child2 = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.0 child:subnodes[2]]; child2.flexGrow = YES; child2.flexShrink = YES; @@ -489,16 +485,12 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex) // Instead it should be stretched to 300 points tall, matching the red child and not overlapping the green inset. ASLayoutSpec *layoutSpec = [ASBackgroundLayoutSpec - newWithChild: + backgroundLayoutSpecWithChild: [ASInsetLayoutSpec - newWithInsets:UIEdgeInsetsMake(10, 10, 10, 10) + insetLayoutSpecWithInsets:UIEdgeInsetsMake(10, 10, 10, 10) child: - [ASStackLayoutSpec - newWithStyle:{ - .direction = ASStackLayoutDirectionHorizontal, - .alignItems = ASStackLayoutAlignItemsStretch, - } - children:@[subnodes[1], child2,]]] + [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal spacing:0 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsStretch children:@[subnodes[1], child2,]] + ] background:subnodes[0]]; static ASSizeRange kSize = {{300, 0}, {300, INFINITY}}; diff --git a/examples/Kittens/Sample/BlurbNode.m b/examples/Kittens/Sample/BlurbNode.m index 1c646a25ad..693ec0cd03 100644 --- a/examples/Kittens/Sample/BlurbNode.m +++ b/examples/Kittens/Sample/BlurbNode.m @@ -76,14 +76,13 @@ static NSString *kLinkAttributeName = @"PlaceKittenNodeLinkAttributeName"; #if UseAutomaticLayout - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize { - return - [ASInsetLayoutSpec - newWithInsets:UIEdgeInsetsMake(kTextPadding, kTextPadding, kTextPadding, kTextPadding) - child: - [ASCenterLayoutSpec - newWithCenteringOptions:ASCenterLayoutSpecCenteringX // Center the text horizontally - sizingOptions:ASCenterLayoutSpecSizingOptionMinimumY // Takes up minimum height - child:_textNode]]; + ASCenterLayoutSpec *centerSpec = [[ASCenterLayoutSpec alloc] init]; + centerSpec.centeringOptions = ASCenterLayoutSpecCenteringX; + centerSpec.sizingOptions = ASCenterLayoutSpecSizingOptionMinimumY; + centerSpec.child = _textNode; + + UIEdgeInsets padding =UIEdgeInsetsMake(kTextPadding, kTextPadding, kTextPadding, kTextPadding); + return [ASInsetLayoutSpec insetLayoutSpecWithInsets:padding child:centerSpec]; } #else - (CGSize)calculateSizeThatFits:(CGSize)constrainedSize diff --git a/examples/Kittens/Sample/KittenNode.mm b/examples/Kittens/Sample/KittenNode.mm index a852bcb801..faf2cc9693 100644 --- a/examples/Kittens/Sample/KittenNode.mm +++ b/examples/Kittens/Sample/KittenNode.mm @@ -137,16 +137,16 @@ static const CGFloat kInnerPadding = 10.0f; _imageNode.preferredFrameSize = _isImageEnlarged ? CGSizeMake(2.0 * kImageSize, 2.0 * kImageSize) : CGSizeMake(kImageSize, kImageSize); _textNode.flexShrink = YES; - return - [ASInsetLayoutSpec - newWithInsets:UIEdgeInsetsMake(kOuterPadding, kOuterPadding, kOuterPadding, kOuterPadding) - child: - [ASStackLayoutSpec - newWithStyle:{ - .direction = ASStackLayoutDirectionHorizontal, - .spacing = kInnerPadding - } - children:!_swappedTextAndImage ? @[_imageNode, _textNode] : @[_textNode, _imageNode]]]; + ASStackLayoutSpec *stackSpec = [[ASStackLayoutSpec alloc] init]; + stackSpec.direction = ASStackLayoutDirectionHorizontal; + stackSpec.spacing = kInnerPadding; + [stackSpec addChildren:!_swappedTextAndImage ? @[_imageNode, _textNode] : @[_textNode, _imageNode]]; + + ASInsetLayoutSpec *insetSpec = [[ASInsetLayoutSpec alloc] init]; + insetSpec.insets = UIEdgeInsetsMake(kOuterPadding, kOuterPadding, kOuterPadding, kOuterPadding); + insetSpec.child = stackSpec; + + return insetSpec; } // With box model, you don't need to override this method, unless you want to add custom logic.