Merge pull request #644 from rcancro/layoutOptions

Added ASLayoutOptions class to store all options for ASLayoutSpecs
This commit is contained in:
appleguy
2015-09-08 22:30:31 -07:00
41 changed files with 808 additions and 314 deletions

View File

@@ -233,6 +233,18 @@
9C3061091B857EC400D0530B /* ASBaselineLayoutSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C3061051B857EC400D0530B /* ASBaselineLayoutSpec.mm */; };
9C49C36F1B853957000B0DD5 /* 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, ); }; };
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.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C5FA3501B8F6ADF00A62714 /* ASLayoutOptions.mm */; };
9C5FA3541B8F6ADF00A62714 /* ASLayoutOptions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C5FA3501B8F6ADF00A62714 /* ASLayoutOptions.mm */; };
9C5FA35D1B90C9A500A62714 /* ASLayoutOptionsPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C5FA35B1B90C9A500A62714 /* ASLayoutOptionsPrivate.h */; settings = {ATTRIBUTES = (Public, ); }; };
9C5FA35E1B90C9A500A62714 /* ASLayoutOptionsPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C5FA35B1B90C9A500A62714 /* ASLayoutOptionsPrivate.h */; settings = {ATTRIBUTES = (Public, ); }; };
9C5FA35F1B90C9A500A62714 /* ASLayoutOptionsPrivate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C5FA35C1B90C9A500A62714 /* ASLayoutOptionsPrivate.mm */; };
9C5FA3601B90C9A500A62714 /* ASLayoutOptionsPrivate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C5FA35C1B90C9A500A62714 /* ASLayoutOptionsPrivate.mm */; };
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, ); }; };
9CDC18CC1B910E12004965E2 /* ASLayoutablePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; };
9CDC18CD1B910E12004965E2 /* ASLayoutablePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; };
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, ); }; };
AC3C4A511A1139C100143C57 /* ASCollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = AC3C4A4F1A1139C100143C57 /* ASCollectionView.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -469,7 +481,7 @@
058D09DD195D050800B7D73C /* ASImageNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASImageNode.h; sourceTree = "<group>"; };
058D09DE195D050800B7D73C /* ASImageNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASImageNode.mm; sourceTree = "<group>"; };
058D09DF195D050800B7D73C /* ASTextNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTextNode.h; sourceTree = "<group>"; };
058D09E0195D050800B7D73C /* ASTextNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASTextNode.mm; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
058D09E0195D050800B7D73C /* ASTextNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASTextNode.mm; sourceTree = "<group>"; };
058D09E2195D050800B7D73C /* _ASDisplayLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASDisplayLayer.h; sourceTree = "<group>"; };
058D09E3195D050800B7D73C /* _ASDisplayLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _ASDisplayLayer.mm; sourceTree = "<group>"; };
058D09E4195D050800B7D73C /* _ASDisplayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASDisplayView.h; sourceTree = "<group>"; };
@@ -580,6 +592,12 @@
9C3061041B857EC400D0530B /* ASBaselineLayoutSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASBaselineLayoutSpec.h; path = AsyncDisplayKit/Layout/ASBaselineLayoutSpec.h; 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>"; };
9C5FA34F1B8F6ADF00A62714 /* ASLayoutOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutOptions.h; path = AsyncDisplayKit/Layout/ASLayoutOptions.h; sourceTree = "<group>"; };
9C5FA3501B8F6ADF00A62714 /* ASLayoutOptions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASLayoutOptions.mm; path = AsyncDisplayKit/Layout/ASLayoutOptions.mm; sourceTree = "<group>"; };
9C5FA35B1B90C9A500A62714 /* ASLayoutOptionsPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutOptionsPrivate.h; path = AsyncDisplayKit/Layout/ASLayoutOptionsPrivate.h; sourceTree = "<group>"; };
9C5FA35C1B90C9A500A62714 /* ASLayoutOptionsPrivate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASLayoutOptionsPrivate.mm; path = AsyncDisplayKit/Layout/ASLayoutOptionsPrivate.mm; sourceTree = "<group>"; };
9C6BB3B01B8CC9C200F13F52 /* ASStaticLayoutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStaticLayoutable.h; path = AsyncDisplayKit/Layout/ASStaticLayoutable.h; sourceTree = "<group>"; };
9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutablePrivate.h; path = AsyncDisplayKit/Layout/ASLayoutablePrivate.h; 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>"; };
AC3C4A4F1A1139C100143C57 /* ASCollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionView.h; sourceTree = "<group>"; };
@@ -983,6 +1001,7 @@
ACF6ED0B1B17843500DA7C62 /* ASLayout.h */,
ACF6ED0C1B17843500DA7C62 /* ASLayout.mm */,
ACF6ED111B17843500DA7C62 /* ASLayoutable.h */,
9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */,
ACF6ED0D1B17843500DA7C62 /* ASLayoutSpec.h */,
ACF6ED0E1B17843500DA7C62 /* ASLayoutSpec.mm */,
ACF6ED121B17843500DA7C62 /* ASOverlayLayoutSpec.h */,
@@ -993,10 +1012,15 @@
AC21EC0F1B3D0BF600C8B19A /* ASStackLayoutDefines.h */,
ACF6ED161B17843500DA7C62 /* ASStackLayoutSpec.h */,
ACF6ED171B17843500DA7C62 /* ASStackLayoutSpec.mm */,
9C6BB3B01B8CC9C200F13F52 /* ASStaticLayoutable.h */,
ACF6ED181B17843500DA7C62 /* ASStaticLayoutSpec.h */,
ACF6ED191B17843500DA7C62 /* ASStaticLayoutSpec.mm */,
9C3061041B857EC400D0530B /* ASBaselineLayoutSpec.h */,
9C3061051B857EC400D0530B /* ASBaselineLayoutSpec.mm */,
9C5FA34F1B8F6ADF00A62714 /* ASLayoutOptions.h */,
9C5FA3501B8F6ADF00A62714 /* ASLayoutOptions.mm */,
9C5FA35B1B90C9A500A62714 /* ASLayoutOptionsPrivate.h */,
9C5FA35C1B90C9A500A62714 /* ASLayoutOptionsPrivate.mm */,
);
name = Layout;
path = ..;
@@ -1046,6 +1070,7 @@
ACF6ED201B17843500DA7C62 /* ASDimension.h in Headers */,
ACF6ED2B1B17843500DA7C62 /* ASOverlayLayoutSpec.h in Headers */,
ACF6ED1C1B17843500DA7C62 /* ASCenterLayoutSpec.h in Headers */,
9C6BB3B21B8CC9C200F13F52 /* ASStaticLayoutable.h in Headers */,
ACF6ED2A1B17843500DA7C62 /* ASLayoutable.h in Headers */,
ACF6ED311B17843500DA7C62 /* ASStaticLayoutSpec.h in Headers */,
ACF6ED241B17843500DA7C62 /* ASLayout.h in Headers */,
@@ -1063,6 +1088,7 @@
058D0A49195D05CB00B7D73C /* ASControlNode+Subclasses.h in Headers */,
058D0A4A195D05CB00B7D73C /* ASDisplayNode.h in Headers */,
1950C4491A3BB5C1005C8279 /* ASEqualityHelpers.h in Headers */,
9C5FA3511B8F6ADF00A62714 /* ASLayoutOptions.h in Headers */,
058D0A4B195D05CB00B7D73C /* ASDisplayNode.mm in Headers */,
430E7C8F1B4C23F100697A4C /* ASIndexPath.h in Headers */,
058D0A4C195D05CB00B7D73C /* ASDisplayNode+Subclasses.h in Headers */,
@@ -1071,6 +1097,7 @@
058D0A4F195D05CB00B7D73C /* ASImageNode.h in Headers */,
058D0A50195D05CB00B7D73C /* ASImageNode.mm in Headers */,
058D0A51195D05CB00B7D73C /* ASTextNode.h in Headers */,
9C5FA35D1B90C9A500A62714 /* ASLayoutOptionsPrivate.h in Headers */,
296A0A2E1A9516B2005ACEAA /* ASBatchFetching.h in Headers */,
058D0A52195D05CB00B7D73C /* ASTextNode.mm in Headers */,
055F1A3819ABD413004DAFF1 /* ASRangeController.h in Headers */,
@@ -1113,6 +1140,7 @@
18C2ED7E1B9B7DE800F627B3 /* ASCollectionNode.h in Headers */,
058D0A6C195D05EC00B7D73C /* _ASAsyncTransactionContainer.m in Headers */,
6BDC61F61979037800E50D21 /* AsyncDisplayKit.h in Headers */,
9CDC18CC1B910E12004965E2 /* ASLayoutablePrivate.h in Headers */,
058D0A6D195D05EC00B7D73C /* _ASAsyncTransactionGroup.h in Headers */,
058D0A6E195D05EC00B7D73C /* _ASAsyncTransactionGroup.m in Headers */,
205F0E1D1B373A2C007741D0 /* ASCollectionViewLayoutController.h in Headers */,
@@ -1161,9 +1189,11 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
9C6BB3B31B8CC9C200F13F52 /* ASStaticLayoutable.h in Headers */,
B35062321B010EFD0018CF92 /* ASTextNodeShadower.h in Headers */,
34EFC7651B701CCC00AD841F /* ASRelativeSize.h in Headers */,
B35062431B010EFD0018CF92 /* UIView+ASConvenience.h in Headers */,
9C5FA35E1B90C9A500A62714 /* ASLayoutOptionsPrivate.h in Headers */,
B31A241E1B0114FD0016AE7A /* AsyncDisplayKit.h in Headers */,
B350622D1B010EFD0018CF92 /* ASScrollDirection.h in Headers */,
B35061FB1B010EFD0018CF92 /* ASDisplayNode.h in Headers */,
@@ -1195,6 +1225,7 @@
B35062391B010EFD0018CF92 /* ASThread.h in Headers */,
B35062131B010EFD0018CF92 /* ASBasicImageDownloader.h in Headers */,
34EFC7791B701D3600AD841F /* ASLayoutSpecUtilities.h in Headers */,
9C5FA3521B8F6ADF00A62714 /* ASLayoutOptions.h in Headers */,
34EFC76A1B701CE600AD841F /* ASLayoutSpec.h in Headers */,
B35062221B010EFD0018CF92 /* ASMultidimensionalArrayUtils.h in Headers */,
B350625B1B010F070018CF92 /* ASEqualityHelpers.h in Headers */,
@@ -1251,6 +1282,7 @@
B35062591B010F070018CF92 /* ASBaseDefines.h in Headers */,
B35062191B010EFD0018CF92 /* ASDealloc2MainObject.h in Headers */,
B350620F1B010EFD0018CF92 /* _ASDisplayLayer.h in Headers */,
9CDC18CD1B910E12004965E2 /* ASLayoutablePrivate.h in Headers */,
B35062531B010EFD0018CF92 /* ASImageNode+CGExtras.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1455,6 +1487,8 @@
ACF6ED2E1B17843500DA7C62 /* ASRatioLayoutSpec.mm in Sources */,
058D0A18195D050800B7D73C /* _ASDisplayLayer.mm in Sources */,
ACF6ED321B17843500DA7C62 /* ASStaticLayoutSpec.mm in Sources */,
9C5FA3531B8F6ADF00A62714 /* ASLayoutOptions.mm in Sources */,
9C5FA35F1B90C9A500A62714 /* ASLayoutOptionsPrivate.mm in Sources */,
ACF6ED2C1B17843500DA7C62 /* ASOverlayLayoutSpec.mm in Sources */,
058D0A2C195D050800B7D73C /* ASSentinel.m in Sources */,
205F0E221B376416007741D0 /* CGRect+ASConvenience.m in Sources */,
@@ -1567,6 +1601,7 @@
B35062471B010EFD0018CF92 /* ASBatchFetching.m in Sources */,
B350624E1B010EFD0018CF92 /* ASDisplayNode+AsyncDisplay.mm in Sources */,
34EFC76F1B701CF700AD841F /* ASRatioLayoutSpec.mm in Sources */,
9C5FA3601B90C9A500A62714 /* ASLayoutOptionsPrivate.mm in Sources */,
34EFC7681B701CDE00AD841F /* ASLayout.mm in Sources */,
B35061F61B010EFD0018CF92 /* ASCollectionView.mm in Sources */,
34EFC75C1B701BD200AD841F /* ASDimension.mm in Sources */,
@@ -1582,6 +1617,7 @@
B350621C1B010EFD0018CF92 /* ASFlowLayoutController.mm in Sources */,
B35062231B010EFD0018CF92 /* ASMultidimensionalArrayUtils.mm in Sources */,
509E68641B3AEDB7009B9150 /* ASCollectionViewLayoutController.mm in Sources */,
9C5FA3541B8F6ADF00A62714 /* ASLayoutOptions.mm in Sources */,
B350621E1B010EFD0018CF92 /* ASHighlightOverlayLayer.mm in Sources */,
B35062271B010EFD0018CF92 /* ASRangeController.mm in Sources */,
18C2ED831B9B7DE800F627B3 /* ASCollectionNode.m in Sources */,

View File

@@ -13,7 +13,7 @@
#import <AsyncDisplayKit/ASDealloc2MainObject.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.
@@ -40,7 +40,7 @@ typedef CALayer *(^ASDisplayNodeLayerBlock)();
*
*/
@interface ASDisplayNode : ASDealloc2MainObject <ASStackLayoutable>
@interface ASDisplayNode : ASDealloc2MainObject <ASLayoutable>
/** @name Initializing a node object */

View File

@@ -9,6 +9,7 @@
#import "ASDisplayNode.h"
#import "ASDisplayNode+Subclasses.h"
#import "ASDisplayNodeInternal.h"
#import "ASLayoutOptionsPrivate.h"
#import <objc/runtime.h>
@@ -41,12 +42,7 @@
@implementation ASDisplayNode
@synthesize spacingBefore = _spacingBefore;
@synthesize spacingAfter = _spacingAfter;
@synthesize flexGrow = _flexGrow;
@synthesize flexShrink = _flexShrink;
@synthesize flexBasis = _flexBasis;
@synthesize alignSelf = _alignSelf;
@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender, sizeRange, layoutPosition, layoutOptions;
@synthesize preferredFrameSize = _preferredFrameSize;
BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector)
@@ -155,7 +151,6 @@ void ASDisplayNodeRespectThreadAffinityOfNode(ASDisplayNode *node, void (^block)
}
_methodOverrides = overrides;
_flexBasis = ASRelativeDimensionUnconstrained;
_preferredFrameSize = CGSizeZero;
}
@@ -1854,6 +1849,11 @@ static void _recursivelySetDisplaySuspended(ASDisplayNode *node, CALayer *layer,
return !self.layerBacked && [self.view canPerformAction:action withSender:sender];
}
- (ASLayoutSpec *)finalLayoutableWithParent:(ASLayoutSpec *)parentSpec
{
return nil;
}
@end
@implementation ASDisplayNode (Debugging)

View File

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

View File

@@ -17,7 +17,6 @@
#import <AsyncDisplayKit/ASTextNodeTextKitHelpers.h>
#import <AsyncDisplayKit/ASDisplayNodeExtras.h>
#import "ASInternalHelpers.h"
#import "ASTextNodeRenderer.h"
#import "ASTextNodeShadower.h"
@@ -108,9 +107,6 @@ ASDISPLAYNODE_INLINE CGFloat ceilPixelValue(CGFloat f)
UILongPressGestureRecognizer *_longPressGestureRecognizer;
}
@synthesize ascender = _ascender;
@synthesize descender = _descender;
#pragma mark - NSObject
- (instancetype)init
@@ -359,9 +355,6 @@ ASDISPLAYNODE_INLINE CGFloat ceilPixelValue(CGFloat f)
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

View File

@@ -15,7 +15,6 @@
*/
@interface ASBackgroundLayoutSpec : ASLayoutSpec
@property (nonatomic, strong) id<ASLayoutable> child;
@property (nonatomic, strong) id<ASLayoutable> background;
/**

View File

@@ -14,11 +14,9 @@
#import "ASBaseDefines.h"
#import "ASLayout.h"
static NSString * const kBackgroundChildKey = @"kBackgroundChildKey";
@interface ASBackgroundLayoutSpec ()
{
id<ASLayoutable> _child;
id<ASLayoutable> _background;
}
@end
@implementation ASBackgroundLayoutSpec
@@ -30,12 +28,11 @@
}
ASDisplayNodeAssertNotNil(child, @"Child cannot be nil");
_child = child;
_background = background;
[self setChild:child];
self.background = background;
return self;
}
+ (instancetype)backgroundLayoutSpecWithChild:(id<ASLayoutable>)child background:(id<ASLayoutable>)background;
{
return [[self alloc] initWithChild:child background:background];
@@ -46,12 +43,12 @@
*/
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
{
ASLayout *contentsLayout = [_child measureWithSizeRange:constrainedSize];
ASLayout *contentsLayout = [[self child] measureWithSizeRange:constrainedSize];
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:2];
if (_background) {
if (self.background) {
// Size background to exactly the same size.
ASLayout *backgroundLayout = [_background measureWithSizeRange:{contentsLayout.size, contentsLayout.size}];
ASLayout *backgroundLayout = [self.background measureWithSizeRange:{contentsLayout.size, contentsLayout.size}];
backgroundLayout.position = CGPointZero;
[sublayouts addObject:backgroundLayout];
}
@@ -63,14 +60,12 @@
- (void)setBackground:(id<ASLayoutable>)background
{
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
_background = background;
[super setChild:background forIdentifier:kBackgroundChildKey];
}
- (void)setChild:(id<ASLayoutable>)child
- (id<ASLayoutable>)background
{
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
_child = child;
return [super childForIdentifier:kBackgroundChildKey];
}
@end

View File

@@ -9,7 +9,7 @@
*/
#import <AsyncDisplayKit/ASStackLayoutSpec.h>
#import <AsyncDisplayKit/ASBaselineLayoutable.h>
#import <AsyncDisplayKit/ASLayoutable.h>
typedef NS_ENUM(NSUInteger, ASBaselineLayoutBaselineAlignment) {
/** 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
baseline instead of from the child's bounding box.
*/
@interface ASBaselineLayoutSpec : ASLayoutSpec <ASBaselineLayoutable>
@interface ASBaselineLayoutSpec : ASLayoutSpec
/** Specifies the direction children are stacked in. */
@property (nonatomic, assign) ASStackLayoutDirection direction;
@@ -42,9 +42,6 @@ typedef NS_ENUM(NSUInteger, ASBaselineLayoutBaselineAlignment) {
/** The type of baseline alignment */
@property (nonatomic, assign) ASBaselineLayoutBaselineAlignment baselineAlignment;
- (void)addChild:(id<ASBaselineLayoutable>)child;
- (void)addChildren:(NSArray *)children;
/**
@param direction The direction of the stack view (horizontal or vertical)
@param spacing The spacing between the children

View File

@@ -9,7 +9,6 @@
*/
#import "ASBaselineLayoutSpec.h"
#import "ASStackLayoutable.h"
#import <numeric>
#import <vector>
@@ -26,13 +25,6 @@
@implementation ASBaselineLayoutSpec
{
std::vector<id<ASStackLayoutable>> _children;
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
{
@@ -47,10 +39,7 @@
_justifyContent = justifyContent;
_baselineAlignment = baselineAlignment;
_children = std::vector<id<ASStackLayoutable>>();
for (id<ASStackLayoutable> child in children) {
_children.push_back(child);
}
[self setChildren:children];
return self;
}
@@ -65,7 +54,12 @@
ASStackLayoutSpecStyle stackStyle = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems};
ASBaselineLayoutSpecStyle style = { .baselineAlignment = _baselineAlignment, .stackLayoutStyle = stackStyle };
const auto unpositionedLayout = ASStackUnpositionedLayout::compute(_children, stackStyle, constrainedSize);
std::vector<id<ASLayoutable>> stackChildren = std::vector<id<ASLayoutable>>();
for (id<ASLayoutable> child in self.children) {
stackChildren.push_back(child);
}
const auto unpositionedLayout = ASStackUnpositionedLayout::compute(stackChildren, stackStyle, constrainedSize);
const auto positionedLayout = ASStackPositionedLayout::compute(unpositionedLayout, stackStyle, constrainedSize);
const auto baselinePositionedLayout = ASBaselinePositionedLayout::compute(positionedLayout, style, constrainedSize);
@@ -73,25 +67,14 @@
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
size:ASSizeRangeClamp(constrainedSize, finalSize)
sublayouts:sublayouts];
}
- (void)addChild:(id<ASBaselineLayoutable>)child
- (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier
{
_children.push_back(child);
}
- (void)addChildren:(NSArray *)children
{
for (id<ASBaselineLayoutable> child in children) {
[self addChild:child];
}
ASDisplayNodeAssert(NO, @"ASBaselineLayoutSpec only supports setChildren");
}
@end

View File

@@ -6,9 +6,9 @@
* 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

View File

@@ -39,7 +39,6 @@ typedef NS_OPTIONS(NSUInteger, ASCenterLayoutSpecSizingOptions) {
@property (nonatomic, assign) ASCenterLayoutSpecCenteringOptions centeringOptions;
@property (nonatomic, assign) ASCenterLayoutSpecSizingOptions sizingOptions;
@property (nonatomic, strong) id<ASLayoutable> child;
/**
* Initializer.

View File

@@ -17,7 +17,6 @@
{
ASCenterLayoutSpecCenteringOptions _centeringOptions;
ASCenterLayoutSpecSizingOptions _sizingOptions;
id<ASLayoutable> _child;
}
- (instancetype)initWithCenteringOptions:(ASCenterLayoutSpecCenteringOptions)centeringOptions
@@ -30,7 +29,7 @@
ASDisplayNodeAssertNotNil(child, @"Child cannot be nil");
_centeringOptions = centeringOptions;
_sizingOptions = sizingOptions;
_child = child;
[self setChild:child];
return self;
}
@@ -41,12 +40,6 @@
return [[self alloc] initWithCenteringOptions:centeringOptions sizingOptions:sizingOptions child:child];
}
- (void)setChild:(id<ASLayoutable>)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");
@@ -71,7 +64,7 @@
(_centeringOptions & ASCenterLayoutSpecCenteringX) != 0 ? 0 : constrainedSize.min.width,
(_centeringOptions & ASCenterLayoutSpecCenteringY) != 0 ? 0 : constrainedSize.min.height,
};
ASLayout *sublayout = [_child measureWithSizeRange:ASSizeRangeMake(minChildSize, constrainedSize.max)];
ASLayout *sublayout = [self.child measureWithSizeRange:ASSizeRangeMake(minChildSize, constrainedSize.max)];
// If we have an undetermined height or width, use the child size to define the layout
// size

View File

@@ -29,7 +29,6 @@
*/
@interface ASInsetLayoutSpec : ASLayoutSpec
@property (nonatomic, strong) id<ASLayoutable> child;
@property (nonatomic, assign) UIEdgeInsets insets;
/**

View File

@@ -19,7 +19,6 @@
@interface ASInsetLayoutSpec ()
{
UIEdgeInsets _insets;
id<ASLayoutable> _child;
}
@end
@@ -50,7 +49,7 @@ static CGFloat centerInset(CGFloat outer, CGFloat inner)
}
ASDisplayNodeAssertNotNil(child, @"Child cannot be nil");
_insets = insets;
_child = child;
[self setChild:child];
return self;
}
@@ -59,12 +58,6 @@ static CGFloat centerInset(CGFloat outer, CGFloat inner)
return [[self alloc] initWithInsets:insets child:child];
}
- (void)setChild:(id<ASLayoutable>)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");
@@ -95,7 +88,7 @@ static CGFloat centerInset(CGFloat outer, CGFloat inner)
MAX(0, constrainedSize.max.height - insetsY),
}
};
ASLayout *sublayout = [_child measureWithSizeRange:insetConstrainedSize];
ASLayout *sublayout = [self.child measureWithSizeRange:insetConstrainedSize];
const CGSize computedSize = ASSizeRangeClamp(constrainedSize, {
finite(sublayout.size.width + _insets.left + _insets.right, constrainedSize.max.width),

View File

@@ -0,0 +1,51 @@
/*
* 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 <Foundation/Foundation.h>
@protocol ASLayoutable;
#import <AsyncDisplayKit/ASBaselineLayoutable.h>
#import <AsyncDisplayKit/ASStackLayoutable.h>
#import <AsyncDisplayKit/ASStaticLayoutable.h>
@interface ASLayoutOptions : NSObject <ASBaselineLayoutable, ASStackLayoutable, ASStaticLayoutable, NSCopying>
+ (void)setDefaultLayoutOptionsClass:(Class)defaultLayoutOptionsClass;
+ (Class)defaultLayoutOptionsClass;
- (instancetype)initWithLayoutable:(id<ASLayoutable>)layoutable;
- (void)setValuesFromLayoutable:(id<ASLayoutable>)layoutable;
#pragma mark - Subclasses should implement these!
- (void)setupDefaults;
- (void)copyIntoOptions:(ASLayoutOptions *)layoutOptions;
#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 layoutPosition;
@end

View File

@@ -0,0 +1,252 @@
/*
* 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 "ASLayoutOptions.h"
#import <AsyncDisplayKit/ASAssert.h>
#import <AsyncDisplayKit/ASThread.h>
#import <AsyncDisplayKit/ASTextNode.h>
#import "ASInternalHelpers.h"
@interface ASLayoutOptions()
{
ASDN::RecursiveMutex _propertyLock;
}
@end
@implementation ASLayoutOptions
@synthesize spacingBefore = _spacingBefore;
@synthesize spacingAfter = _spacingAfter;
@synthesize flexGrow = _flexGrow;
@synthesize flexShrink = _flexShrink;
@synthesize flexBasis = _flexBasis;
@synthesize alignSelf = _alignSelf;
@synthesize ascender = _ascender;
@synthesize descender = _descender;
@synthesize sizeRange = _sizeRange;
@synthesize layoutPosition = _layoutPosition;
static Class gDefaultLayoutOptionsClass = nil;
+ (void)setDefaultLayoutOptionsClass:(Class)defaultLayoutOptionsClass
{
gDefaultLayoutOptionsClass = defaultLayoutOptionsClass;
}
+ (Class)defaultLayoutOptionsClass
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (gDefaultLayoutOptionsClass == nil) {
// If someone is asking for this and it hasn't been customized yet, use the default.
gDefaultLayoutOptionsClass = [ASLayoutOptions class];
}
});
return gDefaultLayoutOptionsClass;
}
- (instancetype)init
{
return [self initWithLayoutable:nil];
}
- (instancetype)initWithLayoutable:(id<ASLayoutable>)layoutable;
{
self = [super init];
if (self) {
[self setupDefaults];
[self setValuesFromLayoutable:layoutable];
}
return self;
}
#pragma mark - NSCopying
- (id)copyWithZone:(NSZone *)zone
{
ASLayoutOptions *copy = [[[self class] alloc] init];
[self copyIntoOptions:copy];
return copy;
}
- (void)copyIntoOptions:(ASLayoutOptions *)copy
{
ASDN::MutexLocker l(_propertyLock);
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.layoutPosition = self.layoutPosition;
}
#pragma mark - Defaults
- (void)setupDefaults
{
self.flexBasis = ASRelativeDimensionUnconstrained;
self.spacingBefore = 0;
self.spacingAfter = 0;
self.flexGrow = NO;
self.flexShrink = NO;
self.alignSelf = ASStackLayoutAlignSelfAuto;
self.ascender = 0;
self.descender = 0;
self.sizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(CGSizeZero), ASRelativeSizeMakeWithCGSize(CGSizeZero));
self.layoutPosition = CGPointZero;
}
// Do this here instead of in Node/Spec subclasses so that custom specs can set default values
- (void)setValuesFromLayoutable:(id<ASLayoutable>)layoutable
{
ASDN::MutexLocker l(_propertyLock);
if ([layoutable isKindOfClass:[ASTextNode class]]) {
ASTextNode *textNode = (ASTextNode *)layoutable;
if (textNode.attributedString.length > 0) {
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.layoutPosition = displayNode.frame.origin;
}
}
- (CGFloat)spacingAfter
{
ASDN::MutexLocker l(_propertyLock);
return _spacingAfter;
}
- (void)setSpacingAfter:(CGFloat)spacingAfter
{
ASDN::MutexLocker l(_propertyLock);
_spacingAfter = spacingAfter;
}
- (CGFloat)spacingBefore
{
ASDN::MutexLocker l(_propertyLock);
return _spacingBefore;
}
- (void)setSpacingBefore:(CGFloat)spacingBefore
{
ASDN::MutexLocker l(_propertyLock);
_spacingBefore = spacingBefore;
}
- (BOOL)flexGrow
{
ASDN::MutexLocker l(_propertyLock);
return _flexGrow;
}
- (void)setFlexGrow:(BOOL)flexGrow
{
ASDN::MutexLocker l(_propertyLock);
_flexGrow = flexGrow;
}
- (BOOL)flexShrink
{
ASDN::MutexLocker l(_propertyLock);
return _flexShrink;
}
- (void)setFlexShrink:(BOOL)flexShrink
{
ASDN::MutexLocker l(_propertyLock);
_flexShrink = flexShrink;
}
- (ASRelativeDimension)flexBasis
{
ASDN::MutexLocker l(_propertyLock);
return _flexBasis;
}
- (void)setFlexBasis:(ASRelativeDimension)flexBasis
{
ASDN::MutexLocker l(_propertyLock);
_flexBasis = flexBasis;
}
- (ASStackLayoutAlignSelf)alignSelf
{
ASDN::MutexLocker l(_propertyLock);
return _alignSelf;
}
- (void)setAlignSelf:(ASStackLayoutAlignSelf)alignSelf
{
ASDN::MutexLocker l(_propertyLock);
_alignSelf = alignSelf;
}
- (CGFloat)ascender
{
ASDN::MutexLocker l(_propertyLock);
return _ascender;
}
- (void)setAscender:(CGFloat)ascender
{
ASDN::MutexLocker l(_propertyLock);
_ascender = ascender;
}
- (CGFloat)descender
{
ASDN::MutexLocker l(_propertyLock);
return _descender;
}
- (void)setDescender:(CGFloat)descender
{
ASDN::MutexLocker l(_propertyLock);
_descender = descender;
}
- (ASRelativeSizeRange)sizeRange
{
ASDN::MutexLocker l(_propertyLock);
return _sizeRange;
}
- (void)setSizeRange:(ASRelativeSizeRange)sizeRange
{
ASDN::MutexLocker l(_propertyLock);
_sizeRange = sizeRange;
}
- (CGPoint)layoutPosition
{
ASDN::MutexLocker l(_propertyLock);
return _layoutPosition;
}
- (void)setLayoutPosition:(CGPoint)layoutPosition
{
ASDN::MutexLocker l(_propertyLock);
_layoutPosition = layoutPosition;
}
@end

View File

@@ -0,0 +1,34 @@
/*
* 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 <AsyncDisplayKit/ASDisplayNode.h>
#import <AsyncDisplayKit/ASLayoutSpec.h>
@interface ASDisplayNode()
{
ASLayoutOptions *_layoutOptions;
dispatch_once_t _layoutOptionsInitializeToken;
}
@end
@interface ASDisplayNode(ASLayoutOptions)<ASLayoutable>
@end
@interface ASLayoutSpec()
{
ASLayoutOptions *_layoutOptions;
dispatch_once_t _layoutOptionsInitializeToken;
}
@end
@interface ASLayoutSpec(ASLayoutOptions)<ASLayoutable>
@end

View File

@@ -0,0 +1,133 @@
/*
* 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 "ASLayoutOptionsPrivate.h"
#import <AsyncDisplayKit/ASDisplayNodeInternal.h>
#define ASLayoutOptionsForwarding \
- (ASLayoutOptions *)layoutOptions\
{\
dispatch_once(&_layoutOptionsInitializeToken, ^{\
if (_layoutOptions == nil) {\
_layoutOptions = [[[ASLayoutOptions defaultLayoutOptionsClass] alloc] initWithLayoutable:self];\
}\
});\
return _layoutOptions;\
}\
\
- (CGFloat)spacingBefore\
{\
return self.layoutOptions.spacingBefore;\
}\
\
- (void)setSpacingBefore:(CGFloat)spacingBefore\
{\
self.layoutOptions.spacingBefore = spacingBefore;\
}\
\
- (CGFloat)spacingAfter\
{\
return self.layoutOptions.spacingAfter;\
}\
\
- (void)setSpacingAfter:(CGFloat)spacingAfter\
{\
self.layoutOptions.spacingAfter = spacingAfter;\
}\
\
- (BOOL)flexGrow\
{\
return self.layoutOptions.flexGrow;\
}\
\
- (void)setFlexGrow:(BOOL)flexGrow\
{\
self.layoutOptions.flexGrow = flexGrow;\
}\
\
- (BOOL)flexShrink\
{\
return self.layoutOptions.flexShrink;\
}\
\
- (void)setFlexShrink:(BOOL)flexShrink\
{\
self.layoutOptions.flexShrink = flexShrink;\
}\
\
- (ASRelativeDimension)flexBasis\
{\
return self.layoutOptions.flexBasis;\
}\
\
- (void)setFlexBasis:(ASRelativeDimension)flexBasis\
{\
self.layoutOptions.flexBasis = flexBasis;\
}\
\
- (ASStackLayoutAlignSelf)alignSelf\
{\
return self.layoutOptions.alignSelf;\
}\
\
- (void)setAlignSelf:(ASStackLayoutAlignSelf)alignSelf\
{\
self.layoutOptions.alignSelf = alignSelf;\
}\
\
- (CGFloat)ascender\
{\
return self.layoutOptions.ascender;\
}\
\
- (void)setAscender:(CGFloat)ascender\
{\
self.layoutOptions.ascender = ascender;\
}\
\
- (CGFloat)descender\
{\
return self.layoutOptions.descender;\
}\
\
- (void)setDescender:(CGFloat)descender\
{\
self.layoutOptions.descender = descender;\
}\
\
- (ASRelativeSizeRange)sizeRange\
{\
return self.layoutOptions.sizeRange;\
}\
\
- (void)setSizeRange:(ASRelativeSizeRange)sizeRange\
{\
self.layoutOptions.sizeRange = sizeRange;\
}\
\
- (CGPoint)layoutPosition\
{\
return self.layoutOptions.layoutPosition;\
}\
\
- (void)setLayoutPosition:(CGPoint)position\
{\
self.layoutOptions.layoutPosition = position;\
}\
@implementation ASDisplayNode(ASLayoutOptions)
ASLayoutOptionsForwarding
@end
@implementation ASLayoutSpec(ASLayoutOptions)
ASLayoutOptionsForwarding
@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. */
@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
@@ -22,4 +22,12 @@
- (instancetype)init;
- (void)setChild:(id<ASLayoutable>)child;
- (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier;
- (void)setChildren:(NSArray *)children;
- (id<ASLayoutable>)child;
- (id<ASLayoutable>)childForIdentifier:(NSString *)identifier;
- (NSArray *)children;
@end

View File

@@ -15,22 +15,29 @@
#import "ASInternalHelpers.h"
#import "ASLayout.h"
#import "ASLayoutOptions.h"
#import "ASLayoutOptionsPrivate.h"
#import <objc/runtime.h>
static NSString * const kDefaultChildKey = @"kDefaultChildKey";
static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey";
@interface ASLayoutSpec()
@property (nonatomic, strong) NSMutableDictionary *layoutChildren;
@end
@implementation ASLayoutSpec
@synthesize spacingBefore = _spacingBefore;
@synthesize spacingAfter = _spacingAfter;
@synthesize flexGrow = _flexGrow;
@synthesize flexShrink = _flexShrink;
@synthesize flexBasis = _flexBasis;
@synthesize alignSelf = _alignSelf;
@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender, sizeRange, layoutPosition, layoutOptions;
@synthesize layoutChildren = _layoutChildren;
- (instancetype)init
{
if (!(self = [super init])) {
return nil;
}
_flexBasis = ASRelativeDimensionUnconstrained;
_layoutChildren = [NSMutableDictionary dictionary];
_isMutable = YES;
return self;
}
@@ -42,4 +49,60 @@
return [ASLayout layoutWithLayoutableObject:self size:constrainedSize.min];
}
- (ASLayoutSpec *)finalLayoutableWithParent:(ASLayoutSpec *)parentSpec;
{
return nil;
}
- (void)setChild:(id<ASLayoutable>)child;
{
[self setChild:child forIdentifier:kDefaultChildKey];
}
- (id<ASLayoutable>)layoutableToAddFromLayoutable:(id<ASLayoutable>)child
{
ASLayoutOptions *layoutOptions = [child layoutOptions];
id<ASLayoutable> finalLayoutable = [child finalLayoutableWithParent:self];
if (finalLayoutable) {
[layoutOptions copyIntoOptions:finalLayoutable.layoutOptions];
return finalLayoutable;
}
return child;
}
- (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier
{
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
self.layoutChildren[identifier] = [self layoutableToAddFromLayoutable: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) {
[finalChildren addObject:[self layoutableToAddFromLayoutable:child]];
}
self.layoutChildren[kDefaultChildrenKey] = [NSArray arrayWithArray:finalChildren];
}
- (id<ASLayoutable>)childForIdentifier:(NSString *)identifier
{
return self.layoutChildren[identifier];
}
- (id<ASLayoutable>)child
{
return self.layoutChildren[kDefaultChildKey];
}
- (NSArray *)children
{
return self.layoutChildren[kDefaultChildrenKey];
}
@end

View File

@@ -9,16 +9,23 @@
*/
#import <AsyncDisplayKit/ASDimension.h>
#import <AsyncDisplayKit/ASRelativeSize.h>
#import <AsyncDisplayKit/ASStackLayoutDefines.h>
#import <AsyncDisplayKit/ASStackLayoutable.h>
#import <AsyncDisplayKit/ASBaselineLayoutable.h>
#import <AsyncDisplayKit/ASStaticLayoutable.h>
#import <AsyncDisplayKit/ASLayoutablePrivate.h>
@class ASLayout;
@class ASLayoutSpec;
/**
* The ASLayoutable protocol declares a method for measuring the layout of an object. A class must implement the method
* so that instances of that class can be used to build layout trees. The protocol also provides information
* about how an object should be laid out within an ASStackLayoutSpec.
*/
@protocol ASLayoutable <NSObject>
@protocol ASLayoutable <ASLayoutablePrivate, ASStackLayoutable, ASBaselineLayoutable, ASStaticLayoutable>
/**
* @abstract Calculate a layout based on given size range.

View File

@@ -0,0 +1,19 @@
/*
* 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 <Foundation/Foundation.h>
@class ASLayoutSpec;
@class ASLayoutOptions;
@protocol ASLayoutablePrivate <NSObject>
- (ASLayoutSpec *)finalLayoutableWithParent:(ASLayoutSpec *)parentSpec;
@property (nonatomic, strong, readonly) ASLayoutOptions *layoutOptions;
@end

View File

@@ -15,7 +15,6 @@
*/
@interface ASOverlayLayoutSpec : ASLayoutSpec
@property (nonatomic, strong) id<ASLayoutable> child;
@property (nonatomic, strong) id<ASLayoutable> overlay;
+ (instancetype)overlayLayoutSpecWithChild:(id<ASLayoutable>)child overlay:(id<ASLayoutable>)overlay;

View File

@@ -14,11 +14,9 @@
#import "ASBaseDefines.h"
#import "ASLayout.h"
static NSString * const kOverlayChildKey = @"kOverlayChildKey";
@implementation ASOverlayLayoutSpec
{
id<ASLayoutable> _overlay;
id<ASLayoutable> _child;
}
- (instancetype)initWithChild:(id<ASLayoutable>)child overlay:(id<ASLayoutable>)overlay
{
@@ -26,8 +24,8 @@
return nil;
}
ASDisplayNodeAssertNotNil(child, @"Child that will be overlayed on shouldn't be nil");
_overlay = overlay;
_child = child;
self.overlay = overlay;
[self setChild:child];
return self;
}
@@ -36,16 +34,14 @@
return [[self alloc] initWithChild:child overlay:overlay];
}
- (void)setChild:(id<ASLayoutable>)child
{
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
_child = child;
}
- (void)setOverlay:(id<ASLayoutable>)overlay
{
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
_overlay = overlay;
[super setChild:overlay forIdentifier:kOverlayChildKey];
}
- (id<ASLayoutable>)overlay
{
return [super childForIdentifier:kOverlayChildKey];
}
/**
@@ -53,11 +49,11 @@
*/
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
{
ASLayout *contentsLayout = [_child measureWithSizeRange:constrainedSize];
ASLayout *contentsLayout = [self.child measureWithSizeRange:constrainedSize];
contentsLayout.position = CGPointZero;
NSMutableArray *sublayouts = [NSMutableArray arrayWithObject:contentsLayout];
if (_overlay) {
ASLayout *overlayLayout = [_overlay measureWithSizeRange:{contentsLayout.size, contentsLayout.size}];
if (self.overlay) {
ASLayout *overlayLayout = [self.overlay measureWithSizeRange:{contentsLayout.size, contentsLayout.size}];
overlayLayout.position = CGPointZero;
[sublayouts addObject:overlayLayout];
}

View File

@@ -31,8 +31,6 @@
**/
@interface ASRatioLayoutSpec : ASLayoutSpec
@property (nonatomic, strong) id<ASLayoutable> child;
@property (nonatomic, assign) CGFloat ratio;
+ (instancetype)ratioLayoutSpecWithRatio:(CGFloat)ratio child:(id<ASLayoutable>)child;

View File

@@ -22,7 +22,6 @@
@implementation ASRatioLayoutSpec
{
CGFloat _ratio;
id<ASLayoutable> _child;
}
+ (instancetype)ratioLayoutSpecWithRatio:(CGFloat)ratio child:(id<ASLayoutable>)child
@@ -38,16 +37,10 @@
ASDisplayNodeAssertNotNil(child, @"Child cannot be nil");
ASDisplayNodeAssert(ratio > 0, @"Ratio should be strictly positive, but received %f", ratio);
_ratio = ratio;
_child = child;
[self setChild:child];
return self;
}
- (void)setChild:(id<ASLayoutable>)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");
@@ -77,7 +70,7 @@
// If there is no max size in *either* dimension, we can't apply the ratio, so just pass our size range through.
const ASSizeRange childRange = (bestSize == sizeOptions.end()) ? constrainedSize : ASSizeRangeMake(*bestSize, *bestSize);
ASLayout *sublayout = [_child measureWithSizeRange:childRange];
ASLayout *sublayout = [self.child measureWithSizeRange:childRange];
sublayout.position = CGPointZero;
return [ASLayout layoutWithLayoutableObject:self size:sublayout.size sublayouts:@[sublayout]];
}

View File

@@ -55,7 +55,4 @@
*/
+ (instancetype)stackLayoutSpecWithDirection:(ASStackLayoutDirection)direction spacing:(CGFloat)spacing justifyContent:(ASStackLayoutJustifyContent)justifyContent alignItems:(ASStackLayoutAlignItems)alignItems children:(NSArray *)children;
- (void)addChild:(id<ASStackLayoutable>)child;
- (void)addChildren:(NSArray *)children;
@end

View File

@@ -23,9 +23,6 @@
#import "ASThread.h"
@implementation ASStackLayoutSpec
{
std::vector<id<ASStackLayoutable>> _children;
}
- (instancetype)init
{
@@ -47,26 +44,10 @@
_spacing = spacing;
_justifyContent = justifyContent;
_children = std::vector<id<ASStackLayoutable>>();
for (id<ASStackLayoutable> child in children) {
_children.push_back(child);
}
[self setChildren:children];
return self;
}
- (void)addChild:(id<ASStackLayoutable>)child
{
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
_children.push_back(child);
}
- (void)addChildren:(NSArray *)children
{
for (id<ASStackLayoutable> child in children) {
[self addChild:child];
}
}
- (void)setDirection:(ASStackLayoutDirection)direction
{
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
@@ -91,10 +72,20 @@
_spacing = spacing;
}
- (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier
{
ASDisplayNodeAssert(NO, @"ASStackLayoutSpec only supports setChildren");
}
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
{
ASStackLayoutSpecStyle style = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems};
const auto unpositionedLayout = ASStackUnpositionedLayout::compute(_children, style, constrainedSize);
std::vector<id<ASLayoutable>> stackChildren = std::vector<id<ASLayoutable>>();
for (id<ASLayoutable> child in self.children) {
stackChildren.push_back(child);
}
const auto unpositionedLayout = ASStackUnpositionedLayout::compute(stackChildren, 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()];

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.

View File

@@ -11,43 +11,6 @@
#import <AsyncDisplayKit/ASLayoutSpec.h>
#import <AsyncDisplayKit/ASRelativeSize.h>
/**
* An ASStaticLayoutSpecChild object wraps an ASLayoutable object and provides position and size information,
* to be used as a child of an ASStaticLayoutSpec.
*/
@interface ASStaticLayoutSpecChild : NSObject
@property (nonatomic, readonly) CGPoint position;
@property (nonatomic, readonly) id<ASLayoutable> layoutableObject;
/**
If specified, the child's size is restricted according to this size. Percentages are resolved relative to the static layout spec.
*/
@property (nonatomic, readonly) ASRelativeSizeRange size;
/**
* Initializer.
*
* @param position The position of this child within its parent spec.
*
* @param layoutableObject The backing ASLayoutable object of this child.
*
* @param size The size range that this child's size is trstricted according to.
*/
+ (instancetype)staticLayoutChildWithPosition:(CGPoint)position layoutableObject:(id<ASLayoutable>)layoutableObject size:(ASRelativeSizeRange)size;
/**
* Convenience initializer with default size is Unconstrained in both dimensions, which sets the child's min size to zero
* and max size to the maximum available space it can consume without overflowing the spec's bounds.
*
* @param position The position of this child within its parent spec.
*
* @param layoutableObject The backing ASLayoutable object of this child.
*/
+ (instancetype)staticLayoutChildWithPosition:(CGPoint)position layoutableObject:(id<ASLayoutable>)layoutableObject;
@end
/**
* A layout spec that positions children at fixed positions.
*
@@ -56,10 +19,8 @@
@interface ASStaticLayoutSpec : ASLayoutSpec
/**
@param children Children to be positioned at fixed positions, each is of type ASStaticLayoutSpecChild.
@param children Children to be positioned at fixed positions, each conforms to ASStaticLayoutable
*/
+ (instancetype)staticLayoutSpecWithChildren:(NSArray *)children;
- (void)addChild:(ASStaticLayoutSpecChild *)child;
@end

View File

@@ -11,33 +11,13 @@
#import "ASStaticLayoutSpec.h"
#import "ASLayoutSpecUtilities.h"
#import "ASLayoutOptions.h"
#import "ASLayoutOptionsPrivate.h"
#import "ASInternalHelpers.h"
#import "ASLayout.h"
@implementation ASStaticLayoutSpecChild
+ (instancetype)staticLayoutChildWithPosition:(CGPoint)position layoutableObject:(id<ASLayoutable>)layoutableObject size:(ASRelativeSizeRange)size;
{
ASStaticLayoutSpecChild *c = [[super alloc] init];
if (c) {
c->_position = position;
c->_layoutableObject = layoutableObject;
c->_size = size;
}
return c;
}
+ (instancetype)staticLayoutChildWithPosition:(CGPoint)position layoutableObject:(id<ASLayoutable>)layoutableObject
{
return [self staticLayoutChildWithPosition:position layoutableObject:layoutableObject size:ASRelativeSizeRangeUnconstrained];
}
@end
#import "ASStaticLayoutable.h"
@implementation ASStaticLayoutSpec
{
NSArray *_children;
}
+ (instancetype)staticLayoutSpecWithChildren:(NSArray *)children
{
@@ -54,16 +34,10 @@
if (!(self = [super init])) {
return nil;
}
_children = children;
self.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
{
CGSize size = {
@@ -71,17 +45,18 @@
constrainedSize.max.height
};
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:_children.count];
for (ASStaticLayoutSpecChild *child in _children) {
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:self.children.count];
for (id<ASLayoutable> child in self.children) {
ASLayoutOptions *layoutOptions = child.layoutOptions;
CGSize autoMaxSize = {
constrainedSize.max.width - child.position.x,
constrainedSize.max.height - child.position.y
constrainedSize.max.width - layoutOptions.layoutPosition.x,
constrainedSize.max.height - layoutOptions.layoutPosition.y
};
ASSizeRange childConstraint = ASRelativeSizeRangeEqualToRelativeSizeRange(ASRelativeSizeRangeUnconstrained, child.size)
ASSizeRange childConstraint = ASRelativeSizeRangeEqualToRelativeSizeRange(ASRelativeSizeRangeUnconstrained, layoutOptions.sizeRange)
? ASSizeRangeMake({0, 0}, autoMaxSize)
: ASRelativeSizeRangeResolve(child.size, size);
ASLayout *sublayout = [child.layoutableObject measureWithSizeRange:childConstraint];
sublayout.position = child.position;
: ASRelativeSizeRangeResolve(layoutOptions.sizeRange, size);
ASLayout *sublayout = [child measureWithSizeRange:childConstraint];
sublayout.position = layoutOptions.layoutPosition;
[sublayouts addObject:sublayout];
}

View File

@@ -0,0 +1,23 @@
/*
* 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 <AsyncDisplayKit/ASRelativeSize.h>
@protocol ASStaticLayoutable
/**
If specified, the child's size is restricted according to this size. Percentages are resolved relative to the static layout spec.
*/
@property (nonatomic, assign) ASRelativeSizeRange sizeRange;
/** The position of this object within its parent spec. */
@property (nonatomic, assign) CGPoint layoutPosition;
@end

View File

@@ -12,18 +12,19 @@
#import "ASLayoutSpecUtilities.h"
#import "ASStackLayoutSpecUtilities.h"
#import "ASLayoutOptions.h"
static CGFloat baselineForItem(const ASBaselineLayoutSpecStyle &style,
const ASLayout *layout) {
__weak id<ASBaselineLayoutable> child = (id<ASBaselineLayoutable>) layout.layoutableObject;
__weak id<ASLayoutable> child = layout.layoutableObject;
switch (style.baselineAlignment) {
case ASBaselineLayoutBaselineAlignmentNone:
return 0;
case ASBaselineLayoutBaselineAlignmentFirst:
return child.ascender;
return child.layoutOptions.ascender;
case ASBaselineLayoutBaselineAlignmentLast:
return layout.size.height + child.descender;
return layout.size.height + child.layoutOptions.descender;
}
}
@@ -34,10 +35,10 @@ static CGFloat baselineOffset(const ASBaselineLayoutSpecStyle &style,
const CGFloat maxBaseline)
{
if (style.stackLayoutStyle.direction == ASStackLayoutDirectionHorizontal) {
__weak id<ASBaselineLayoutable> child = (id<ASBaselineLayoutable>)l.layoutableObject;
__weak id<ASLayoutable> child = l.layoutableObject;
switch (style.baselineAlignment) {
case ASBaselineLayoutBaselineAlignmentFirst:
return maxAscender - child.ascender;
return maxAscender - child.layoutOptions.ascender;
case ASBaselineLayoutBaselineAlignmentLast:
return maxBaseline - baselineForItem(style, l);
case ASBaselineLayoutBaselineAlignmentNone:
@@ -91,9 +92,9 @@ 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.
*/
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;
return a.layoutableObject.layoutOptions.ascender < b.layoutableObject.layoutOptions.ascender;
});
const CGFloat maxAscender = baselineIt == positionedLayout.sublayouts.end() ? 0 : ((id<ASBaselineLayoutable>)(*ascenderIt).layoutableObject).ascender;
const CGFloat maxAscender = baselineIt == positionedLayout.sublayouts.end() ? 0 : (*ascenderIt).layoutableObject.layoutOptions.ascender;
/*
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;
BOOL first = YES;
auto stackedChildren = AS::map(positionedLayout.sublayouts, [&](ASLayout *l) -> ASLayout *{
__weak id<ASBaselineLayoutable> child = (id<ASBaselineLayoutable>) l.layoutableObject;
p = p + directionPoint(stackStyle.direction, child.spacingBefore, 0);
__weak id<ASLayoutable> child = l.layoutableObject;
p = p + directionPoint(stackStyle.direction, child.layoutOptions.spacingBefore, 0);
if (first) {
// if this is the first item use the previously computed start point
p = l.position;
@@ -124,9 +125,9 @@ ASBaselinePositionedLayout ASBaselinePositionedLayout::compute(const ASStackPosi
// node from baselines and not bounding boxes.
CGFloat spacingAfterBaseline = 0;
if (stackStyle.direction == ASStackLayoutDirectionVertical) {
spacingAfterBaseline = child.descender;
spacingAfterBaseline = child.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) + child.layoutOptions.spacingAfter + spacingAfterBaseline, 0);
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
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){
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 : (*descenderIt).layoutableObject.layoutOptions.descender;
return {stackedChildren, crossSize, maxAscender, minDescender};
}

View File

@@ -17,6 +17,7 @@
#import "ASDisplayNode.h"
#import "ASSentinel.h"
#import "ASThread.h"
#import "ASLayoutOptions.h"
BOOL ASDisplayNodeSubclassOverridesSelector(Class subclass, SEL selector);
void ASDisplayNodePerformBlockOnMainThread(void (^block)());
@@ -71,7 +72,7 @@ typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides) {
NSMutableSet *_pendingDisplayNodes;
_ASPendingState *_pendingViewState;
struct {
// public properties
unsigned synchronous:1;

View File

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

View File

@@ -16,7 +16,7 @@
struct ASStackUnpositionedItem {
/** The original source child. */
id<ASStackLayoutable> child;
id<ASLayoutable> child;
/** The proposed layout. */
ASLayout *layout;
};
@@ -31,7 +31,7 @@ struct ASStackUnpositionedLayout {
const CGFloat violation;
/** 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 ASSizeRange &sizeRange);
};

View File

@@ -14,18 +14,19 @@
#import "ASLayoutSpecUtilities.h"
#import "ASStackLayoutSpecUtilities.h"
#import "ASLayoutOptions.h"
/**
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 CGFloat stackMin,
const CGFloat stackMax,
const CGFloat crossMin,
const CGFloat crossMax)
{
const ASStackLayoutAlignItems alignItems = alignment(child.alignSelf, style.alignItems);
const ASStackLayoutAlignItems alignItems = alignment(child.layoutOptions.alignSelf, style.alignItems);
// stretched children will have a cross dimension of at least crossMin
const CGFloat childCrossMin = alignItems == ASStackLayoutAlignItemsStretch ? crossMin : 0;
const ASSizeRange childSizeRange = directionSizeRange(style.direction, stackMin, stackMax, childCrossMin, crossMax);
@@ -75,7 +76,7 @@ static void stretchChildrenAlongCrossDimension(std::vector<ASStackUnpositionedIt
const CGFloat childCrossMax = it == layouts.end() ? 0 : crossDimension(style.direction, it->layout.size);
for (auto &l : layouts) {
const ASStackLayoutAlignItems alignItems = alignment(l.child.alignSelf, style.alignItems);
const ASStackLayoutAlignItems alignItems = alignment(l.child.layoutOptions.alignSelf, style.alignItems);
const CGFloat cross = crossDimension(style.direction, l.layout.size);
const CGFloat stack = stackDimension(style.direction, l.layout.size);
@@ -111,7 +112,7 @@ static CGFloat computeStackDimensionSum(const std::vector<ASStackUnpositionedIte
// Start from default spacing between each child:
children.empty() ? 0 : style.spacing * (children.size() - 1),
[&](CGFloat x, const ASStackUnpositionedItem &l) {
return x + l.child.spacingBefore + l.child.spacingAfter;
return x + l.child.layoutOptions.spacingBefore + l.child.layoutOptions.spacingAfter;
});
// Sum up the childrens' dimensions (including spacing) in the stack direction.
@@ -180,22 +181,22 @@ static std::function<BOOL(const ASStackUnpositionedItem &)> isFlexibleInViolatio
if (fabs(violation) < kViolationEpsilon) {
return [](const ASStackUnpositionedItem &l) { return NO; };
} else if (violation > 0) {
return [](const ASStackUnpositionedItem &l) { return l.child.flexGrow; };
return [](const ASStackUnpositionedItem &l) { return l.child.layoutOptions.flexGrow; };
} else {
return [](const ASStackUnpositionedItem &l) { return l.child.flexShrink; };
return [](const ASStackUnpositionedItem &l) { return l.child.layoutOptions.flexShrink; };
}
}
ASDISPLAYNODE_INLINE BOOL isFlexibleInBothDirections(id<ASStackLayoutable> child)
ASDISPLAYNODE_INLINE BOOL isFlexibleInBothDirections(id<ASLayoutable> child)
{
return child.flexGrow && child.flexShrink;
return child.layoutOptions.flexGrow && child.layoutOptions.flexShrink;
}
/**
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.
*/
ASDISPLAYNODE_INLINE BOOL useOptimizedFlexing(const std::vector<id<ASStackLayoutable>> &children,
ASDISPLAYNODE_INLINE BOOL useOptimizedFlexing(const std::vector<id<ASLayoutable>> &children,
const ASStackLayoutSpecStyle &style,
const ASSizeRange &sizeRange)
{
@@ -283,7 +284,7 @@ static void flexChildrenAlongStackDimension(std::vector<ASStackUnpositionedItem>
Performs the first unconstrained layout of the children, generating the unpositioned items that are then flexed and
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 ASSizeRange &sizeRange,
const CGSize size,
@@ -292,9 +293,9 @@ static std::vector<ASStackUnpositionedItem> layoutChildrenAlongUnconstrainedStac
const CGFloat minCrossDimension = crossDimension(style.direction, sizeRange.min);
const CGFloat maxCrossDimension = crossDimension(style.direction, sizeRange.max);
return AS::map(children, [&](id<ASStackLayoutable> child) -> ASStackUnpositionedItem {
const BOOL isUnconstrainedFlexBasis = ASRelativeDimensionEqualToRelativeDimension(ASRelativeDimensionUnconstrained, child.flexBasis);
const CGFloat exactStackDimension = ASRelativeDimensionResolve(child.flexBasis, stackDimension(style.direction, size));
return AS::map(children, [&](id<ASLayoutable> child) -> ASStackUnpositionedItem {
const BOOL isUnconstrainedFlexBasis = ASRelativeDimensionEqualToRelativeDimension(ASRelativeDimensionUnconstrained, child.layoutOptions.flexBasis);
const CGFloat exactStackDimension = ASRelativeDimensionResolve(child.layoutOptions.flexBasis, stackDimension(style.direction, size));
if (useOptimizedFlexing && isFlexibleInBothDirections(child)) {
return { child, [ASLayout layoutWithLayoutableObject:child size:{0, 0}] };
@@ -312,7 +313,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 ASSizeRange &sizeRange)
{

View File

@@ -13,6 +13,7 @@
#import "ASBackgroundLayoutSpec.h"
#import "ASCenterLayoutSpec.h"
#import "ASStackLayoutSpec.h"
#import "ASLayoutOptions.h"
static const ASSizeRange kSize = {{100, 120}, {320, 160}};
@@ -94,7 +95,7 @@ static NSString *suffixForCenteringOptions(ASCenterLayoutSpecCenteringOptions ce
ASDisplayNode *backgroundNode = ASDisplayNodeWithBackgroundColor([UIColor redColor]);
ASStaticSizeDisplayNode *foregroundNode = ASDisplayNodeWithBackgroundColor([UIColor redColor]);
foregroundNode.staticSize = {10, 10};
foregroundNode.flexGrow = YES;
foregroundNode.layoutOptions.flexGrow = YES;
ASCenterLayoutSpec *layoutSpec =
[ASCenterLayoutSpec

View File

@@ -15,6 +15,7 @@
#import "ASBackgroundLayoutSpec.h"
#import "ASRatioLayoutSpec.h"
#import "ASInsetLayoutSpec.h"
#import "ASLayoutOptions.h"
@interface ASStackLayoutSpecSnapshotTests : ASLayoutSpecSnapshotTestCase
@end
@@ -41,8 +42,8 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
];
for (ASStaticSizeDisplayNode *subnode in subnodes) {
subnode.staticSize = subnodeSize;
subnode.flexGrow = flex;
subnode.flexShrink = flex;
subnode.layoutOptions.flexGrow = flex;
subnode.layoutOptions.flexShrink = flex;
}
return subnodes;
}
@@ -114,7 +115,7 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
ASStackLayoutSpecStyle style = {.direction = ASStackLayoutDirectionHorizontal};
NSArray *subnodes = defaultSubnodesWithSameSize({50, 50}, NO);
((ASDisplayNode *)subnodes[1]).flexShrink = YES;
((ASDisplayNode *)subnodes[1]).layoutOptions.flexShrink = YES;
// 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}};
@@ -204,23 +205,23 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 10;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 10;
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 20;
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingBefore"];
// Reset above spacing values
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingAfter = 10;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingAfter = 20;
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingAfter = 10;
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingAfter = 20;
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingAfter"];
// Reset above spacing values
((ASStaticSizeDisplayNode *)subnodes[1]).spacingAfter = 0;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingAfter = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingAfter = 0;
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingAfter = 0;
style.spacing = 10;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = -10;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingAfter = -10;
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = -10;
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingAfter = -10;
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingBalancedOut"];
}
@@ -236,9 +237,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30;
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 30;
// width 0-300px; height 300px
static ASSizeRange kVariableHeight = {{0, 300}, {300, 300}};
@@ -254,9 +255,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
subnode2.staticSize = {50, 50};
ASRatioLayoutSpec *child1 = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.5 child:subnode1];
child1.flexBasis = ASRelativeDimensionMakeWithPercent(1);
child1.flexGrow = YES;
child1.flexShrink = YES;
child1.layoutOptions.flexBasis = ASRelativeDimensionMakeWithPercent(1);
child1.layoutOptions.flexGrow = YES;
child1.layoutOptions.flexShrink = YES;
static ASSizeRange kFixedWidth = {{150, 0}, {150, INFINITY}};
[self testStackLayoutSpecWithStyle:style children:@[child1, subnode2] sizeRange:kFixedWidth subnodes:@[subnode1, subnode2] identifier:nil];
@@ -271,11 +272,11 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
ASStaticSizeDisplayNode *subnode1 = ASDisplayNodeWithBackgroundColor([UIColor redColor]);
subnode1.staticSize = {100, 100};
subnode1.flexShrink = YES;
subnode1.layoutOptions.flexShrink = YES;
ASStaticSizeDisplayNode *subnode2 = ASDisplayNodeWithBackgroundColor([UIColor blueColor]);
subnode2.staticSize = {50, 50};
subnode2.flexShrink = YES;
subnode2.layoutOptions.flexShrink = YES;
NSArray *subnodes = @[subnode1, subnode2];
static ASSizeRange kFixedWidth = {{150, 0}, {150, 100}};
@@ -291,7 +292,7 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
ASStaticSizeDisplayNode *subnode2 = ASDisplayNodeWithBackgroundColor([UIColor blueColor]);
subnode2.staticSize = {50, 50};
subnode2.alignSelf = ASStackLayoutAlignSelfCenter;
subnode2.layoutOptions.alignSelf = ASStackLayoutAlignSelfCenter;
NSArray *subnodes = @[subnode1, subnode2];
static ASSizeRange kFixedWidth = {{150, 0}, {150, INFINITY}};
@@ -311,9 +312,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30;
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 30;
static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
@@ -332,9 +333,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30;
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 30;
static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
@@ -353,9 +354,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30;
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 30;
static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
@@ -374,9 +375,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30;
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 30;
static ASSizeRange kVariableSize = {{200, 200}, {300, 300}};
// all children should be 200px wide
@@ -396,9 +397,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30;
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.spacingBefore = 0;
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 20;
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 30;
static ASSizeRange kVariableSize = {{50, 50}, {300, 300}};
// all children should be 150px wide
@@ -419,8 +420,8 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {150, 150};
for (ASStaticSizeDisplayNode *subnode in subnodes) {
subnode.flexGrow = YES;
subnode.flexBasis = ASRelativeDimensionMakeWithPoints(10);
subnode.layoutOptions.flexGrow = YES;
subnode.layoutOptions.flexBasis = ASRelativeDimensionMakeWithPoints(10);
}
// width 300px; height 0-150px.
@@ -439,12 +440,12 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
NSArray *subnodes = defaultSubnodesWithSameSize({50, 50}, NO);
for (ASStaticSizeDisplayNode *subnode in subnodes) {
subnode.flexGrow = YES;
subnode.layoutOptions.flexGrow = YES;
}
// 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.
((ASStaticSizeDisplayNode *)subnodes[0]).flexBasis = ASRelativeDimensionMakeWithPercent(0.5);
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.flexBasis = ASRelativeDimensionMakeWithPercent(0.5);
static ASSizeRange kSize = {{200, 0}, {200, INFINITY}};
[self testStackLayoutSpecWithStyle:style sizeRange:kSize subnodes:subnodes identifier:nil];
@@ -460,7 +461,7 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {50, 50};
for (ASStaticSizeDisplayNode *subnode in subnodes) {
subnode.flexBasis = ASRelativeDimensionMakeWithPoints(20);
subnode.layoutOptions.flexBasis = ASRelativeDimensionMakeWithPoints(20);
}
static ASSizeRange kSize = {{300, 0}, {300, 150}};
@@ -478,8 +479,8 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {3000, 3000};
ASRatioLayoutSpec *child2 = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.0 child:subnodes[2]];
child2.flexGrow = YES;
child2.flexShrink = YES;
child2.layoutOptions.flexGrow = YES;
child2.layoutOptions.flexShrink = YES;
// 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.
@@ -504,13 +505,13 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
NSArray *subnodes = defaultSubnodes();
((ASStaticSizeDisplayNode *)subnodes[0]).staticSize = {300, 50};
((ASStaticSizeDisplayNode *)subnodes[0]).flexShrink = YES;
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.flexShrink = YES;
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 50};
((ASStaticSizeDisplayNode *)subnodes[1]).flexShrink = NO;
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.flexShrink = NO;
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {200, 50};
((ASStaticSizeDisplayNode *)subnodes[2]).flexShrink = YES;
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.flexShrink = YES;
// 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.

View File

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

View File

@@ -136,12 +136,11 @@ static const CGFloat kInnerPadding = 10.0f;
{
_imageNode.preferredFrameSize = _isImageEnlarged ? CGSizeMake(2.0 * kImageSize, 2.0 * kImageSize) : CGSizeMake(kImageSize, kImageSize);
_textNode.flexShrink = YES;
_textNode.flexGrow = YES;
ASStackLayoutSpec *stackSpec = [[ASStackLayoutSpec alloc] init];
stackSpec.direction = ASStackLayoutDirectionHorizontal;
stackSpec.spacing = kInnerPadding;
[stackSpec addChildren:!_swappedTextAndImage ? @[_imageNode, _textNode] : @[_textNode, _imageNode]];
[stackSpec setChildren:!_swappedTextAndImage ? @[_imageNode, _textNode] : @[_textNode, _imageNode]];
ASInsetLayoutSpec *insetSpec = [[ASInsetLayoutSpec alloc] init];
insetSpec.insets = UIEdgeInsetsMake(kOuterPadding, kOuterPadding, kOuterPadding, kOuterPadding);