diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index e9aa51e544..e2e2e1e87e 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -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 = ""; }; 058D09DE195D050800B7D73C /* ASImageNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASImageNode.mm; sourceTree = ""; }; 058D09DF195D050800B7D73C /* ASTextNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTextNode.h; sourceTree = ""; }; - 058D09E0195D050800B7D73C /* ASTextNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASTextNode.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 058D09E0195D050800B7D73C /* ASTextNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASTextNode.mm; sourceTree = ""; }; 058D09E2195D050800B7D73C /* _ASDisplayLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASDisplayLayer.h; sourceTree = ""; }; 058D09E3195D050800B7D73C /* _ASDisplayLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _ASDisplayLayer.mm; sourceTree = ""; }; 058D09E4195D050800B7D73C /* _ASDisplayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASDisplayView.h; sourceTree = ""; }; @@ -580,6 +592,12 @@ 9C3061041B857EC400D0530B /* ASBaselineLayoutSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASBaselineLayoutSpec.h; path = AsyncDisplayKit/Layout/ASBaselineLayoutSpec.h; sourceTree = ""; }; 9C3061051B857EC400D0530B /* ASBaselineLayoutSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASBaselineLayoutSpec.mm; path = AsyncDisplayKit/Layout/ASBaselineLayoutSpec.mm; sourceTree = ""; }; 9C49C36E1B853957000B0DD5 /* ASStackLayoutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStackLayoutable.h; path = AsyncDisplayKit/Layout/ASStackLayoutable.h; sourceTree = ""; }; + 9C5FA34F1B8F6ADF00A62714 /* ASLayoutOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutOptions.h; path = AsyncDisplayKit/Layout/ASLayoutOptions.h; sourceTree = ""; }; + 9C5FA3501B8F6ADF00A62714 /* ASLayoutOptions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASLayoutOptions.mm; path = AsyncDisplayKit/Layout/ASLayoutOptions.mm; sourceTree = ""; }; + 9C5FA35B1B90C9A500A62714 /* ASLayoutOptionsPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutOptionsPrivate.h; path = AsyncDisplayKit/Layout/ASLayoutOptionsPrivate.h; sourceTree = ""; }; + 9C5FA35C1B90C9A500A62714 /* ASLayoutOptionsPrivate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASLayoutOptionsPrivate.mm; path = AsyncDisplayKit/Layout/ASLayoutOptionsPrivate.mm; sourceTree = ""; }; + 9C6BB3B01B8CC9C200F13F52 /* ASStaticLayoutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStaticLayoutable.h; path = AsyncDisplayKit/Layout/ASStaticLayoutable.h; sourceTree = ""; }; + 9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutablePrivate.h; path = AsyncDisplayKit/Layout/ASLayoutablePrivate.h; sourceTree = ""; }; 9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCollectionViewTests.m; sourceTree = ""; }; AC21EC0F1B3D0BF600C8B19A /* ASStackLayoutDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASStackLayoutDefines.h; path = AsyncDisplayKit/Layout/ASStackLayoutDefines.h; sourceTree = ""; }; AC3C4A4F1A1139C100143C57 /* ASCollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionView.h; sourceTree = ""; }; @@ -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 */, diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index 974bbe1272..7fcfbd5999 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -13,7 +13,7 @@ #import #import -#import +#import /** * UIView creation block. Used to create the backing view of a new display node. @@ -40,7 +40,7 @@ typedef CALayer *(^ASDisplayNodeLayerBlock)(); * */ -@interface ASDisplayNode : ASDealloc2MainObject +@interface ASDisplayNode : ASDealloc2MainObject /** @name Initializing a node object */ diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 05698813f4..4dcf41e26e 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -9,6 +9,7 @@ #import "ASDisplayNode.h" #import "ASDisplayNode+Subclasses.h" #import "ASDisplayNodeInternal.h" +#import "ASLayoutOptionsPrivate.h" #import @@ -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) diff --git a/AsyncDisplayKit/ASTextNode.h b/AsyncDisplayKit/ASTextNode.h index 1b35441c81..e8d5b76154 100644 --- a/AsyncDisplayKit/ASTextNode.h +++ b/AsyncDisplayKit/ASTextNode.h @@ -7,7 +7,6 @@ */ #import -#import @protocol ASTextNodeDelegate; @@ -30,7 +29,7 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) { @abstract Draws interactive rich text. @discussion Backed by TextKit. */ -@interface ASTextNode : ASControlNode +@interface ASTextNode : ASControlNode /** @abstract The attributed string to show. diff --git a/AsyncDisplayKit/ASTextNode.mm b/AsyncDisplayKit/ASTextNode.mm index 7ca68f5177..68f4f1fdab 100644 --- a/AsyncDisplayKit/ASTextNode.mm +++ b/AsyncDisplayKit/ASTextNode.mm @@ -17,7 +17,6 @@ #import #import -#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 diff --git a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h index ecc2e48473..cab51ea8b3 100644 --- a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h @@ -15,7 +15,6 @@ */ @interface ASBackgroundLayoutSpec : ASLayoutSpec -@property (nonatomic, strong) id child; @property (nonatomic, strong) id background; /** diff --git a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm index fd3cfce134..ea18aca990 100644 --- a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm @@ -14,11 +14,9 @@ #import "ASBaseDefines.h" #import "ASLayout.h" +static NSString * const kBackgroundChildKey = @"kBackgroundChildKey"; + @interface ASBackgroundLayoutSpec () -{ - id _child; - id _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)child background:(id)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)background { - ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); - _background = background; + [super setChild:background forIdentifier:kBackgroundChildKey]; } -- (void)setChild:(id)child +- (id)background { - ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); - _child = child; + return [super childForIdentifier:kBackgroundChildKey]; } @end diff --git a/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.h b/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.h index 8b784a56c3..d147c76700 100644 --- a/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.h @@ -9,7 +9,7 @@ */ #import -#import +#import 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 +@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)child; -- (void)addChildren:(NSArray *)children; - /** @param direction The direction of the stack view (horizontal or vertical) @param spacing The spacing between the children diff --git a/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.mm b/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.mm index 670c69c991..50139a548b 100644 --- a/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASBaselineLayoutSpec.mm @@ -9,7 +9,6 @@ */ #import "ASBaselineLayoutSpec.h" -#import "ASStackLayoutable.h" #import #import @@ -26,13 +25,6 @@ @implementation ASBaselineLayoutSpec -{ - std::vector> _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>(); - for (id 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> stackChildren = std::vector>(); + for (id 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)child +- (void)setChild:(id)child forIdentifier:(NSString *)identifier { - _children.push_back(child); -} - -- (void)addChildren:(NSArray *)children -{ - for (id child in children) { - [self addChild:child]; - } + ASDisplayNodeAssert(NO, @"ASBaselineLayoutSpec only supports setChildren"); } @end diff --git a/AsyncDisplayKit/Layout/ASBaselineLayoutable.h b/AsyncDisplayKit/Layout/ASBaselineLayoutable.h index 5e05029964..7e52b2c056 100644 --- a/AsyncDisplayKit/Layout/ASBaselineLayoutable.h +++ b/AsyncDisplayKit/Layout/ASBaselineLayoutable.h @@ -6,9 +6,9 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import "ASStackLayoutable.h" +#import -@protocol ASBaselineLayoutable +@protocol ASBaselineLayoutable /** * @abstract The distance from the top of the layoutable object to its baseline diff --git a/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h b/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h index dc50b265e7..37ba24e7e7 100644 --- a/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h @@ -39,7 +39,6 @@ typedef NS_OPTIONS(NSUInteger, ASCenterLayoutSpecSizingOptions) { @property (nonatomic, assign) ASCenterLayoutSpecCenteringOptions centeringOptions; @property (nonatomic, assign) ASCenterLayoutSpecSizingOptions sizingOptions; -@property (nonatomic, strong) id child; /** * Initializer. diff --git a/AsyncDisplayKit/Layout/ASCenterLayoutSpec.mm b/AsyncDisplayKit/Layout/ASCenterLayoutSpec.mm index 1830895320..58dc55f962 100644 --- a/AsyncDisplayKit/Layout/ASCenterLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASCenterLayoutSpec.mm @@ -17,7 +17,6 @@ { ASCenterLayoutSpecCenteringOptions _centeringOptions; ASCenterLayoutSpecSizingOptions _sizingOptions; - id _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)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 diff --git a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.h b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.h index 3b140dfcc7..ab0a6f106f 100644 --- a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.h @@ -29,7 +29,6 @@ */ @interface ASInsetLayoutSpec : ASLayoutSpec -@property (nonatomic, strong) id child; @property (nonatomic, assign) UIEdgeInsets insets; /** diff --git a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm index 5ca96ab848..cc6ec9411a 100644 --- a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm @@ -19,7 +19,6 @@ @interface ASInsetLayoutSpec () { UIEdgeInsets _insets; - id _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)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), diff --git a/AsyncDisplayKit/Layout/ASLayoutOptions.h b/AsyncDisplayKit/Layout/ASLayoutOptions.h new file mode 100644 index 0000000000..022bbb61f3 --- /dev/null +++ b/AsyncDisplayKit/Layout/ASLayoutOptions.h @@ -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 + +@protocol ASLayoutable; + +#import +#import +#import + +@interface ASLayoutOptions : NSObject + ++ (void)setDefaultLayoutOptionsClass:(Class)defaultLayoutOptionsClass; ++ (Class)defaultLayoutOptionsClass; + +- (instancetype)initWithLayoutable:(id)layoutable; +- (void)setValuesFromLayoutable:(id)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 diff --git a/AsyncDisplayKit/Layout/ASLayoutOptions.mm b/AsyncDisplayKit/Layout/ASLayoutOptions.mm new file mode 100644 index 0000000000..9e499bd172 --- /dev/null +++ b/AsyncDisplayKit/Layout/ASLayoutOptions.mm @@ -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 +#import +#import +#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)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)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 diff --git a/AsyncDisplayKit/Layout/ASLayoutOptionsPrivate.h b/AsyncDisplayKit/Layout/ASLayoutOptionsPrivate.h new file mode 100644 index 0000000000..b00e09580a --- /dev/null +++ b/AsyncDisplayKit/Layout/ASLayoutOptionsPrivate.h @@ -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 +#import + + +@interface ASDisplayNode() +{ + ASLayoutOptions *_layoutOptions; + dispatch_once_t _layoutOptionsInitializeToken; +} +@end + +@interface ASDisplayNode(ASLayoutOptions) +@end + +@interface ASLayoutSpec() +{ + ASLayoutOptions *_layoutOptions; + dispatch_once_t _layoutOptionsInitializeToken; +} +@end + +@interface ASLayoutSpec(ASLayoutOptions) +@end + diff --git a/AsyncDisplayKit/Layout/ASLayoutOptionsPrivate.mm b/AsyncDisplayKit/Layout/ASLayoutOptionsPrivate.mm new file mode 100644 index 0000000000..39d129ba11 --- /dev/null +++ b/AsyncDisplayKit/Layout/ASLayoutOptionsPrivate.mm @@ -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 + + +#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 diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.h b/AsyncDisplayKit/Layout/ASLayoutSpec.h index bb200cbfe1..f132d5d7f5 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.h @@ -8,10 +8,10 @@ * */ -#import +#import /** A layout spec is an immutable object that describes a layout, loosely inspired by React. */ -@interface ASLayoutSpec : NSObject +@interface ASLayoutSpec : NSObject /** 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)child; +- (void)setChild:(id)child forIdentifier:(NSString *)identifier; +- (void)setChildren:(NSArray *)children; + +- (id)child; +- (id)childForIdentifier:(NSString *)identifier; +- (NSArray *)children; + @end diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index ef09aa365e..0985014b80 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -15,22 +15,29 @@ #import "ASInternalHelpers.h" #import "ASLayout.h" +#import "ASLayoutOptions.h" +#import "ASLayoutOptionsPrivate.h" + +#import + +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)child; +{ + [self setChild:child forIdentifier:kDefaultChildKey]; +} + +- (id)layoutableToAddFromLayoutable:(id)child +{ + ASLayoutOptions *layoutOptions = [child layoutOptions]; + + id finalLayoutable = [child finalLayoutableWithParent:self]; + if (finalLayoutable) { + [layoutOptions copyIntoOptions:finalLayoutable.layoutOptions]; + return finalLayoutable; + } + return child; +} + +- (void)setChild:(id)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 child in children) { + [finalChildren addObject:[self layoutableToAddFromLayoutable:child]]; + } + + self.layoutChildren[kDefaultChildrenKey] = [NSArray arrayWithArray:finalChildren]; +} + +- (id)childForIdentifier:(NSString *)identifier +{ + return self.layoutChildren[identifier]; +} + +- (id)child +{ + return self.layoutChildren[kDefaultChildKey]; +} + +- (NSArray *)children +{ + return self.layoutChildren[kDefaultChildrenKey]; +} + + @end diff --git a/AsyncDisplayKit/Layout/ASLayoutable.h b/AsyncDisplayKit/Layout/ASLayoutable.h index 4ac01ee05f..38644c0b60 100644 --- a/AsyncDisplayKit/Layout/ASLayoutable.h +++ b/AsyncDisplayKit/Layout/ASLayoutable.h @@ -9,16 +9,23 @@ */ #import +#import #import +#import +#import +#import + +#import @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 +@protocol ASLayoutable /** * @abstract Calculate a layout based on given size range. diff --git a/AsyncDisplayKit/Layout/ASLayoutablePrivate.h b/AsyncDisplayKit/Layout/ASLayoutablePrivate.h new file mode 100644 index 0000000000..2d317fc7ca --- /dev/null +++ b/AsyncDisplayKit/Layout/ASLayoutablePrivate.h @@ -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 + +@class ASLayoutSpec; +@class ASLayoutOptions; + +@protocol ASLayoutablePrivate +- (ASLayoutSpec *)finalLayoutableWithParent:(ASLayoutSpec *)parentSpec; +@property (nonatomic, strong, readonly) ASLayoutOptions *layoutOptions; +@end diff --git a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.h b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.h index 35a9577dde..05e53d92e8 100644 --- a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.h @@ -15,7 +15,6 @@ */ @interface ASOverlayLayoutSpec : ASLayoutSpec -@property (nonatomic, strong) id child; @property (nonatomic, strong) id overlay; + (instancetype)overlayLayoutSpecWithChild:(id)child overlay:(id)overlay; diff --git a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm index f4f025573b..b71375f5be 100644 --- a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm @@ -14,11 +14,9 @@ #import "ASBaseDefines.h" #import "ASLayout.h" +static NSString * const kOverlayChildKey = @"kOverlayChildKey"; + @implementation ASOverlayLayoutSpec -{ - id _overlay; - id _child; -} - (instancetype)initWithChild:(id)child overlay:(id)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)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; + [super setChild:overlay forIdentifier:kOverlayChildKey]; +} + +- (id)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]; } diff --git a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.h b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.h index fd7f6d657b..2affa56a75 100644 --- a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.h @@ -31,8 +31,6 @@ **/ @interface ASRatioLayoutSpec : ASLayoutSpec - -@property (nonatomic, strong) id child; @property (nonatomic, assign) CGFloat ratio; + (instancetype)ratioLayoutSpecWithRatio:(CGFloat)ratio child:(id)child; diff --git a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm index 5e5c6f0c66..64e9e2c118 100644 --- a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm @@ -22,7 +22,6 @@ @implementation ASRatioLayoutSpec { CGFloat _ratio; - id _child; } + (instancetype)ratioLayoutSpecWithRatio:(CGFloat)ratio child:(id)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)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]]; } diff --git a/AsyncDisplayKit/Layout/ASStackLayoutSpec.h b/AsyncDisplayKit/Layout/ASStackLayoutSpec.h index 7825a9b8fc..b5a126c5cb 100644 --- a/AsyncDisplayKit/Layout/ASStackLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASStackLayoutSpec.h @@ -55,7 +55,4 @@ */ + (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 3149979dd6..ef109d47ae 100644 --- a/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm @@ -23,9 +23,6 @@ #import "ASThread.h" @implementation ASStackLayoutSpec -{ - std::vector> _children; -} - (instancetype)init { @@ -47,26 +44,10 @@ _spacing = spacing; _justifyContent = justifyContent; - _children = std::vector>(); - for (id child in children) { - _children.push_back(child); - } + [self setChildren:children]; 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"); @@ -91,10 +72,20 @@ _spacing = spacing; } +- (void)setChild:(id)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> stackChildren = std::vector>(); + for (id 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()]; diff --git a/AsyncDisplayKit/Layout/ASStackLayoutable.h b/AsyncDisplayKit/Layout/ASStackLayoutable.h index b23b4fbbdb..e26d0a0210 100644 --- a/AsyncDisplayKit/Layout/ASStackLayoutable.h +++ b/AsyncDisplayKit/Layout/ASStackLayoutable.h @@ -8,9 +8,10 @@ * */ -#import +#import +#import -@protocol ASStackLayoutable +@protocol ASStackLayoutable /** * @abstract Additional space to place before this object in the stacking direction. diff --git a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.h b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.h index 38ed2f06d6..8bd3f3d9f2 100644 --- a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.h @@ -11,43 +11,6 @@ #import #import -/** - * 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 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)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)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 diff --git a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm index eca2637acd..e9f47c2ecd 100644 --- a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm @@ -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)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)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 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]; } diff --git a/AsyncDisplayKit/Layout/ASStaticLayoutable.h b/AsyncDisplayKit/Layout/ASStaticLayoutable.h new file mode 100644 index 0000000000..f2e565a7a9 --- /dev/null +++ b/AsyncDisplayKit/Layout/ASStaticLayoutable.h @@ -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 + +@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 diff --git a/AsyncDisplayKit/Private/ASBaselinePositionedLayout.mm b/AsyncDisplayKit/Private/ASBaselinePositionedLayout.mm index 2e3d2b3bfe..bf01ff179e 100644 --- a/AsyncDisplayKit/Private/ASBaselinePositionedLayout.mm +++ b/AsyncDisplayKit/Private/ASBaselinePositionedLayout.mm @@ -12,18 +12,19 @@ #import "ASLayoutSpecUtilities.h" #import "ASStackLayoutSpecUtilities.h" +#import "ASLayoutOptions.h" static CGFloat baselineForItem(const ASBaselineLayoutSpecStyle &style, const ASLayout *layout) { - __weak id child = (id) layout.layoutableObject; + __weak id 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 child = (id)l.layoutableObject; + __weak id 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)a.layoutableObject).ascender < ((id)b.layoutableObject).ascender; + return a.layoutableObject.layoutOptions.ascender < b.layoutableObject.layoutOptions.ascender; }); - const CGFloat maxAscender = baselineIt == positionedLayout.sublayouts.end() ? 0 : ((id)(*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 child = (id) l.layoutableObject; - p = p + directionPoint(stackStyle.direction, child.spacingBefore, 0); + __weak id 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)(*descenderIt).layoutableObject).descender; + const CGFloat minDescender = descenderIt == stackedChildren.end() ? 0 : (*descenderIt).layoutableObject.layoutOptions.descender; return {stackedChildren, crossSize, maxAscender, minDescender}; } diff --git a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h index 5a8883ed02..cff5d76461 100644 --- a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h +++ b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h @@ -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; diff --git a/AsyncDisplayKit/Private/ASStackPositionedLayout.mm b/AsyncDisplayKit/Private/ASStackPositionedLayout.mm index 84bbdac502..95b445043c 100644 --- a/AsyncDisplayKit/Private/ASStackPositionedLayout.mm +++ b/AsyncDisplayKit/Private/ASStackPositionedLayout.mm @@ -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}; diff --git a/AsyncDisplayKit/Private/ASStackUnpositionedLayout.h b/AsyncDisplayKit/Private/ASStackUnpositionedLayout.h index 93a2efcb20..4112af8e66 100644 --- a/AsyncDisplayKit/Private/ASStackUnpositionedLayout.h +++ b/AsyncDisplayKit/Private/ASStackUnpositionedLayout.h @@ -16,7 +16,7 @@ struct ASStackUnpositionedItem { /** The original source child. */ - id child; + id 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> &children, + static ASStackUnpositionedLayout compute(const std::vector> &children, const ASStackLayoutSpecStyle &style, const ASSizeRange &sizeRange); }; diff --git a/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm b/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm index cc3be53d1c..7514507a01 100644 --- a/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm +++ b/AsyncDisplayKit/Private/ASStackUnpositionedLayout.mm @@ -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 child, +static ASLayout *crossChildLayout(const id 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::vectorlayout.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 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 child) +ASDISPLAYNODE_INLINE BOOL isFlexibleInBothDirections(id 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> &children, +ASDISPLAYNODE_INLINE BOOL useOptimizedFlexing(const std::vector> &children, const ASStackLayoutSpecStyle &style, const ASSizeRange &sizeRange) { @@ -283,7 +284,7 @@ static void flexChildrenAlongStackDimension(std::vector Performs the first unconstrained layout of the children, generating the unpositioned items that are then flexed and stretched. */ -static std::vector layoutChildrenAlongUnconstrainedStackDimension(const std::vector> &children, +static std::vector layoutChildrenAlongUnconstrainedStackDimension(const std::vector> &children, const ASStackLayoutSpecStyle &style, const ASSizeRange &sizeRange, const CGSize size, @@ -292,9 +293,9 @@ static std::vector layoutChildrenAlongUnconstrainedStac const CGFloat minCrossDimension = crossDimension(style.direction, sizeRange.min); const CGFloat maxCrossDimension = crossDimension(style.direction, sizeRange.max); - return AS::map(children, [&](id child) -> ASStackUnpositionedItem { - const BOOL isUnconstrainedFlexBasis = ASRelativeDimensionEqualToRelativeDimension(ASRelativeDimensionUnconstrained, child.flexBasis); - const CGFloat exactStackDimension = ASRelativeDimensionResolve(child.flexBasis, stackDimension(style.direction, size)); + return AS::map(children, [&](id 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 layoutChildrenAlongUnconstrainedStac }); } -ASStackUnpositionedLayout ASStackUnpositionedLayout::compute(const std::vector> &children, +ASStackUnpositionedLayout ASStackUnpositionedLayout::compute(const std::vector> &children, const ASStackLayoutSpecStyle &style, const ASSizeRange &sizeRange) { diff --git a/AsyncDisplayKitTests/ASCenterLayoutSpecSnapshotTests.mm b/AsyncDisplayKitTests/ASCenterLayoutSpecSnapshotTests.mm index 5a7cbd0a92..45e167afd7 100644 --- a/AsyncDisplayKitTests/ASCenterLayoutSpecSnapshotTests.mm +++ b/AsyncDisplayKitTests/ASCenterLayoutSpecSnapshotTests.mm @@ -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 diff --git a/AsyncDisplayKitTests/ASStackLayoutSpecSnapshotTests.mm b/AsyncDisplayKitTests/ASStackLayoutSpecSnapshotTests.mm index 9b6c3d655d..fbd893940b 100644 --- a/AsyncDisplayKitTests/ASStackLayoutSpecSnapshotTests.mm +++ b/AsyncDisplayKitTests/ASStackLayoutSpecSnapshotTests.mm @@ -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. diff --git a/examples/Kittens/Sample.xcodeproj/project.pbxproj b/examples/Kittens/Sample.xcodeproj/project.pbxproj index 293b513d1e..1e08bbe8c1 100644 --- a/examples/Kittens/Sample.xcodeproj/project.pbxproj +++ b/examples/Kittens/Sample.xcodeproj/project.pbxproj @@ -58,7 +58,9 @@ 1A943BF0259746F18D6E423F /* Frameworks */, 1AE410B73DA5C3BD087ACDD7 /* Pods */, ); + indentWidth = 2; sourceTree = ""; + tabWidth = 2; }; 05E2128219D4DB510098F589 /* Products */ = { isa = PBXGroup; diff --git a/examples/Kittens/Sample/KittenNode.mm b/examples/Kittens/Sample/KittenNode.mm index 0afd654bf8..d1f49351a2 100644 --- a/examples/Kittens/Sample/KittenNode.mm +++ b/examples/Kittens/Sample/KittenNode.mm @@ -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);