[Layout] Improve Layout System Abstraction (#2941)

* Improve Layout Abstraction

* Address naming comments

- Rename ASPrimitiveTraitEnvironment to ASTraitEnvironment
- Rename ASPrimitiveTraitCollectionPropagateDown to ASTraitCollectionPropagateDown
- Rename progagateNewPrimitiveTraitCollection: to propagateNewTraitCollection:
This commit is contained in:
Michael Schneider 2017-02-03 13:04:20 -08:00 committed by GitHub
parent a2ff2b9900
commit 12e4e5b048
50 changed files with 725 additions and 831 deletions

View File

@ -154,7 +154,6 @@
697B315A1CFE4B410049936F /* ASEditableTextNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 697B31591CFE4B410049936F /* ASEditableTextNodeTests.m */; };
698371DB1E4379CD00437585 /* ASNodeController+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = 698371D91E4379CD00437585 /* ASNodeController+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; };
698371DC1E4379CD00437585 /* ASNodeController+Beta.m in Sources */ = {isa = PBXBuildFile; fileRef = 698371DA1E4379CD00437585 /* ASNodeController+Beta.m */; };
698548641CA9E025008A345F /* ASEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 698548611CA9E025008A345F /* ASEnvironment.h */; settings = {ATTRIBUTES = (Public, ); }; };
698C8B621CAB49FC0052DC3F /* ASLayoutElementExtensibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 698C8B601CAB49FC0052DC3F /* ASLayoutElementExtensibility.h */; settings = {ATTRIBUTES = (Public, ); }; };
698DFF441E36B6C9002891F1 /* ASStackLayoutSpecUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 698DFF431E36B6C9002891F1 /* ASStackLayoutSpecUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
698DFF471E36B7E9002891F1 /* ASLayoutSpecUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 698DFF461E36B7E9002891F1 /* ASLayoutSpecUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
@ -162,8 +161,6 @@
69CB62AC1CB8165900024920 /* _ASDisplayViewAccessiblity.h in Headers */ = {isa = PBXBuildFile; fileRef = 69CB62A91CB8165900024920 /* _ASDisplayViewAccessiblity.h */; settings = {ATTRIBUTES = (Private, ); }; };
69CB62AE1CB8165900024920 /* _ASDisplayViewAccessiblity.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69CB62AA1CB8165900024920 /* _ASDisplayViewAccessiblity.mm */; };
69E0E8A71D356C9400627613 /* ASEqualityHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 1950C4481A3BB5C1005C8279 /* ASEqualityHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; };
69E1006E1CA89CB600D88C1B /* ASEnvironmentInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 69E100691CA89CB600D88C1B /* ASEnvironmentInternal.h */; settings = {ATTRIBUTES = (Private, ); }; };
69E100701CA89CB600D88C1B /* ASEnvironmentInternal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */; };
69F10C871C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = 69F10C851C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; };
69FEE53D1D95A9AF0086F066 /* ASLayoutElementStyleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 69FEE53C1D95A9AF0086F066 /* ASLayoutElementStyleTests.m */; };
7630FFA81C9E267E007A7C0E /* ASVideoNode.h in Headers */ = {isa = PBXBuildFile; fileRef = AEEC47DF1C20C2DD00EC1693 /* ASVideoNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -192,7 +189,6 @@
9C6BB3B31B8CC9C200F13F52 /* ASAbsoluteLayoutElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C6BB3B01B8CC9C200F13F52 /* ASAbsoluteLayoutElement.h */; settings = {ATTRIBUTES = (Public, ); }; };
9C70F2051CDA4F06007D6C76 /* ASTraitCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C70F2021CDA4EFA007D6C76 /* ASTraitCollection.m */; };
9C70F2061CDA4F0C007D6C76 /* ASTraitCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C70F2011CDA4EFA007D6C76 /* ASTraitCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
9C70F2081CDAA3C6007D6C76 /* ASEnvironment.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6BD1CCAC52B006A6476 /* ASEnvironment.mm */; };
9C70F2091CDABA36007D6C76 /* ASViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6BF1CCAC73C006A6476 /* ASViewController.mm */; };
9C70F20A1CDBE949007D6C76 /* ASTableNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6C11CCAC768006A6476 /* ASTableNode.mm */; };
9C70F20B1CDBE9A4007D6C76 /* ASDataController+Subclasses.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF61BBB3D690087C538 /* ASDataController+Subclasses.h */; settings = {ATTRIBUTES = (Private, ); }; };
@ -594,7 +590,6 @@
697B31591CFE4B410049936F /* ASEditableTextNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASEditableTextNodeTests.m; sourceTree = "<group>"; };
698371D91E4379CD00437585 /* ASNodeController+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASNodeController+Beta.h"; sourceTree = "<group>"; };
698371DA1E4379CD00437585 /* ASNodeController+Beta.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ASNodeController+Beta.m"; sourceTree = "<group>"; };
698548611CA9E025008A345F /* ASEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASEnvironment.h; sourceTree = "<group>"; };
698C8B601CAB49FC0052DC3F /* ASLayoutElementExtensibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutElementExtensibility.h; path = AsyncDisplayKit/Layout/ASLayoutElementExtensibility.h; sourceTree = "<group>"; };
698DFF431E36B6C9002891F1 /* ASStackLayoutSpecUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASStackLayoutSpecUtilities.h; sourceTree = "<group>"; };
698DFF461E36B7E9002891F1 /* ASLayoutSpecUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutSpecUtilities.h; sourceTree = "<group>"; };
@ -602,8 +597,6 @@
69B225681D7265DA00B25B22 /* ASXCTExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASXCTExtensions.h; sourceTree = "<group>"; };
69CB62A91CB8165900024920 /* _ASDisplayViewAccessiblity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASDisplayViewAccessiblity.h; sourceTree = "<group>"; };
69CB62AA1CB8165900024920 /* _ASDisplayViewAccessiblity.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _ASDisplayViewAccessiblity.mm; sourceTree = "<group>"; };
69E100691CA89CB600D88C1B /* ASEnvironmentInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASEnvironmentInternal.h; sourceTree = "<group>"; };
69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASEnvironmentInternal.mm; sourceTree = "<group>"; };
69F10C851C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASRangeControllerUpdateRangeProtocol+Beta.h"; sourceTree = "<group>"; };
69FEE53C1D95A9AF0086F066 /* ASLayoutElementStyleTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASLayoutElementStyleTests.m; sourceTree = "<group>"; };
6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; path = AsyncDisplayKit.h; sourceTree = "<group>"; };
@ -635,7 +628,6 @@
9C70F2021CDA4EFA007D6C76 /* ASTraitCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTraitCollection.m; sourceTree = "<group>"; };
9C8898BA1C738B9800D6B02E /* ASTextKitFontSizeAdjuster.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASTextKitFontSizeAdjuster.mm; path = TextKit/ASTextKitFontSizeAdjuster.mm; sourceTree = "<group>"; };
9CDC18CB1B910E12004965E2 /* ASLayoutElementPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutElementPrivate.h; path = AsyncDisplayKit/Layout/ASLayoutElementPrivate.h; sourceTree = "<group>"; };
9CFFC6BD1CCAC52B006A6476 /* ASEnvironment.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASEnvironment.mm; sourceTree = "<group>"; };
9CFFC6BF1CCAC73C006A6476 /* ASViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASViewController.mm; sourceTree = "<group>"; };
9CFFC6C11CCAC768006A6476 /* ASTableNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTableNode.mm; sourceTree = "<group>"; };
9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = ASCollectionViewTests.mm; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
@ -1072,8 +1064,6 @@
68C215571DE10D330019C4BC /* ASCollectionViewLayoutInspector.m */,
205F0E1B1B373A2C007741D0 /* ASCollectionViewLayoutController.h */,
205F0E1C1B373A2C007741D0 /* ASCollectionViewLayoutController.mm */,
698548611CA9E025008A345F /* ASEnvironment.h */,
9CFFC6BD1CCAC52B006A6476 /* ASEnvironment.mm */,
4640521B1A3F83C40061C0BA /* ASFlowLayoutController.h */,
4640521C1A3F83C40061C0BA /* ASFlowLayoutController.mm */,
058D09E6195D050800B7D73C /* ASHighlightOverlayLayer.h */,
@ -1180,8 +1170,6 @@
058D0A0C195D050800B7D73C /* ASDisplayNodeInternal.h */,
6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */,
6959433C1D70815300B0EE1F /* ASDisplayNodeLayout.mm */,
69E100691CA89CB600D88C1B /* ASEnvironmentInternal.h */,
69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */,
696F01EA1DD2AF450049FBD5 /* ASEventLog.h */,
696F01EB1DD2AF450049FBD5 /* ASEventLog.mm */,
68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */,
@ -1409,7 +1397,6 @@
6907C2581DC4ECFE00374C66 /* ASObjectDescriptionHelpers.h in Headers */,
69E0E8A71D356C9400627613 /* ASEqualityHelpers.h in Headers */,
698C8B621CAB49FC0052DC3F /* ASLayoutElementExtensibility.h in Headers */,
698548641CA9E025008A345F /* ASEnvironment.h in Headers */,
69F10C871C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h in Headers */,
B350623C1B010EFD0018CF92 /* _ASAsyncTransaction.h in Headers */,
68355B411CB57A6C001D4E68 /* ASImageContainerProtocolCategories.h in Headers */,
@ -1530,7 +1517,6 @@
254C6B7B1BF94DF4003EC431 /* ASTextKitRenderer+Positioning.h in Headers */,
DE4843DC1C93EAC100A1F33B /* ASLayoutTransition.h in Headers */,
CC57EAF81E3939450034C595 /* ASTableView+Undeprecated.h in Headers */,
69E1006E1CA89CB600D88C1B /* ASEnvironmentInternal.h in Headers */,
DE89C1701DCEB9CC00D49D74 /* ASLayoutElementInspectorCell.h in Headers */,
254C6B781BF94DF4003EC431 /* ASTextKitContext.h in Headers */,
9CDC18CD1B910E12004965E2 /* ASLayoutElementPrivate.h in Headers */,
@ -1860,7 +1846,6 @@
690ED59B1E36D118000627C0 /* ASImageNode+tvOS.m in Sources */,
34EFC7621B701CA400AD841F /* ASBackgroundLayoutSpec.mm in Sources */,
DE8BEAC41C2DF3FC00D57C12 /* ASDelegateProxy.m in Sources */,
9C70F2081CDAA3C6007D6C76 /* ASEnvironment.mm in Sources */,
B35062141B010EFD0018CF92 /* ASBasicImageDownloader.mm in Sources */,
B35062161B010EFD0018CF92 /* ASBatchContext.mm in Sources */,
AC47D9421B3B891B00AAEE9D /* ASCellNode.mm in Sources */,
@ -1883,7 +1868,6 @@
636EA1A41C7FF4EC00EE152F /* NSArray+Diffing.m in Sources */,
B35062501B010EFD0018CF92 /* ASDisplayNode+DebugTiming.mm in Sources */,
DEC146B91C37A16A004A0EE7 /* ASCollectionInternal.m in Sources */,
69E100701CA89CB600D88C1B /* ASEnvironmentInternal.mm in Sources */,
254C6B891BF94F8A003EC431 /* ASTextKitRenderer+Positioning.mm in Sources */,
68355B341CB579B9001D4E68 /* ASImageNode+AnimatedImage.mm in Sources */,
E5711A301C840C96009619D4 /* ASIndexedNodeContext.mm in Sources */,

View File

@ -17,7 +17,6 @@
#import <AsyncDisplayKit/ASDisplayNode+Beta.h>
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
#import <AsyncDisplayKit/ASEnvironmentInternal.h>
#import <AsyncDisplayKit/ASInternalHelpers.h>
#import <AsyncDisplayKit/ASCellNode+Internal.h>
#import <AsyncDisplayKit/AsyncDisplayKit+Debug.h>
@ -596,9 +595,9 @@
}
}
#pragma mark ASEnvironment
#pragma mark - ASPrimitiveTraitCollection
ASEnvironmentCollectionTableSetEnvironmentState(_environmentStateLock)
ASLayoutElementCollectionTableSetTraitCollection(_environmentStateLock)
#pragma mark - Debugging (Private)

View File

@ -1460,7 +1460,7 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
}
}
- (id<ASEnvironment>)dataControllerEnvironment
- (id<ASTraitEnvironment>)dataControllerEnvironment
{
return self.collectionNode;
}

View File

@ -107,7 +107,7 @@ extern NSInteger const ASDefaultDrawingPriority;
*
*/
@interface ASDisplayNode : NSObject <ASLayoutElement>
@interface ASDisplayNode : NSObject <ASLayoutElement, ASLayoutElementStylability, NSFastEnumeration>
/** @name Initializing a node object */

View File

@ -28,7 +28,6 @@
#import <AsyncDisplayKit/_ASScopeTimer.h>
#import <AsyncDisplayKit/ASDimension.h>
#import <AsyncDisplayKit/ASDisplayNodeExtras.h>
#import <AsyncDisplayKit/ASEnvironmentInternal.h>
#import <AsyncDisplayKit/ASEqualityHelpers.h>
#import <AsyncDisplayKit/ASInternalHelpers.h>
#import <AsyncDisplayKit/ASLayoutElementStylePrivate.h>
@ -81,7 +80,6 @@
@dynamic layoutElementType;
@synthesize debugName = _debugName;
@synthesize isFinalLayoutElement = _isFinalLayoutElement;
@synthesize threadSafeBounds = _threadSafeBounds;
@synthesize layoutSpecBlock = _layoutSpecBlock;
@ -289,7 +287,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
_contentsScaleForDisplay = ASScreenScale();
_environmentState = ASEnvironmentStateMakeDefault();
_primitiveTraitCollection = ASPrimitiveTraitCollectionMakeDefault();
_calculatedDisplayNodeLayout = std::make_shared<ASDisplayNodeLayout>();
_pendingDisplayNodeLayout = nullptr;
@ -811,12 +809,6 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
return _style;
}
- (instancetype)styledWithBlock:(void (^)(ASLayoutElementStyle *style))styleBlock
{
styleBlock(self.style);
return self;
}
- (ASLayoutElementType)layoutElementType
{
return ASLayoutElementTypeDisplayNode;
@ -827,11 +819,19 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
return !self.isNodeLoaded;
}
- (id<ASLayoutElement>)finalLayoutElement
- (NSArray<id<ASLayoutElement>> *)sublayoutElements
{
return self.subnodes;
}
- (instancetype)styledWithBlock:(AS_NOESCAPE void (^)(__kindof ASLayoutElementStyle *style))styleBlock
{
styleBlock(self.style);
return self;
}
ASLayoutElementFinalLayoutElementDefault
- (NSString *)debugName
{
ASDN::MutexLocker l(__instanceLock__);
@ -1120,8 +1120,9 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
// Manually propagate the trait collection here so that any layoutSpec children of layoutSpec will get a traitCollection
{
ASDN::SumScopeTimer t(_layoutSpecTotalTime, measureLayoutSpec);
ASEnvironmentStatePropagateDown(layoutElement, [self environmentTraitCollection]);
ASTraitCollectionPropagateDown(layoutElement, self.primitiveTraitCollection);
}
BOOL measureLayoutComputation = _measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutComputation;
@ -2487,7 +2488,8 @@ ASDISPLAYNODE_INLINE BOOL nodeIsInRasterizedTree(ASDisplayNode *node) {
}
// Now that we have a supernode, propagate its traits to self.
ASEnvironmentStatePropagateDown(self, [newSupernode environmentTraitCollection]);
ASTraitCollectionPropagateDown(self, newSupernode.primitiveTraitCollection);
} else {
// If a node will be removed from the supernode it should go out from the layout pending state to remove all
// layout pending state related properties on the node
@ -3851,48 +3853,18 @@ ASDISPLAYNODE_INLINE BOOL nodeIsInRasterizedTree(ASDisplayNode *node) {
return [self.subnodes countByEnumeratingWithState:state objects:buffer count:len];
}
#pragma mark - ASEnvironment
#pragma mark - ASPrimitiveTraitCollection
- (ASEnvironmentState)environmentState
- (ASPrimitiveTraitCollection)primitiveTraitCollection
{
return _environmentState;
return _primitiveTraitCollection;
}
- (void)setEnvironmentState:(ASEnvironmentState)environmentState
- (void)setPrimitiveTraitCollection:(ASPrimitiveTraitCollection)traitCollection
{
ASEnvironmentTraitCollection oldTraitCollection = _environmentState.environmentTraitCollection;
_environmentState = environmentState;
if (ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(oldTraitCollection, _environmentState.environmentTraitCollection) == NO) {
[self asyncTraitCollectionDidChange];
}
}
- (ASDisplayNode *)parent
{
return self.supernode;
}
- (NSArray<ASDisplayNode *> *)children
{
return self.subnodes;
}
- (BOOL)supportsTraitsCollectionPropagation
{
return ASEnvironmentStateTraitCollectionPropagationEnabled();
}
- (ASEnvironmentTraitCollection)environmentTraitCollection
{
return _environmentState.environmentTraitCollection;
}
- (void)setEnvironmentTraitCollection:(ASEnvironmentTraitCollection)environmentTraitCollection
{
if (ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(environmentTraitCollection, _environmentState.environmentTraitCollection) == NO) {
_environmentState.environmentTraitCollection = environmentTraitCollection;
ASDisplayNodeLogEvent(self, @"asyncTraitCollectionDidChange: %@", NSStringFromASEnvironmentTraitCollection(environmentTraitCollection));
if (ASPrimitiveTraitCollectionIsEqualToASPrimitiveTraitCollection(traitCollection, _primitiveTraitCollection) == NO) {
_primitiveTraitCollection = traitCollection;
ASDisplayNodeLogEvent(self, @"asyncTraitCollectionDidChange: %@", NSStringFromASPrimitiveTraitCollection(traitCollection));
[self asyncTraitCollectionDidChange];
}
}
@ -3900,7 +3872,7 @@ ASDISPLAYNODE_INLINE BOOL nodeIsInRasterizedTree(ASDisplayNode *node) {
- (ASTraitCollection *)asyncTraitCollection
{
ASDN::MutexLocker l(__instanceLock__);
return [ASTraitCollection traitCollectionWithASEnvironmentTraitCollection:self.environmentTraitCollection];
return [ASTraitCollection traitCollectionWithASPrimitiveTraitCollection:self.primitiveTraitCollection];
}
- (void)asyncTraitCollectionDidChange
@ -3908,7 +3880,11 @@ ASDISPLAYNODE_INLINE BOOL nodeIsInRasterizedTree(ASDisplayNode *node) {
// Subclass override
}
ASEnvironmentLayoutExtensibilityForwarding
ASPrimitiveTraitCollectionDeprecatedImplementation
#pragma mark - ASLayoutElementStyleExtensibility
ASLayoutElementStyleExtensibilityForwarding
#if TARGET_OS_TV
#pragma mark - UIFocusEnvironment Protocol (tvOS)

View File

@ -12,7 +12,6 @@
#import <AsyncDisplayKit/ASTableNode.h>
#import <AsyncDisplayKit/ASTableViewInternal.h>
#import <AsyncDisplayKit/ASEnvironmentInternal.h>
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
#import <AsyncDisplayKit/ASInternalHelpers.h>
@ -356,7 +355,7 @@
#pragma mark ASEnvironment
ASEnvironmentCollectionTableSetEnvironmentState(_environmentStateLock)
ASLayoutElementCollectionTableSetTraitCollection(_environmentStateLock)
#pragma mark - Range Tuning

View File

@ -1668,7 +1668,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
#pragma mark - ASDataControllerEnvironmentDelegate
- (id<ASEnvironment>)dataControllerEnvironment
- (id<ASTraitEnvironment>)dataControllerEnvironment
{
return self.tableNode;
}

View File

@ -16,7 +16,6 @@
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
#import <AsyncDisplayKit/ASLayout.h>
#import <AsyncDisplayKit/ASTraitCollection.h>
#import <AsyncDisplayKit/ASEnvironmentInternal.h>
#import <AsyncDisplayKit/ASRangeControllerUpdateRangeProtocol+Beta.h>
#import <AsyncDisplayKit/ASInternalHelpers.h>
@ -102,8 +101,8 @@
// ensure that self.node has a valid trait collection before a subclass's implementation of viewDidLoad.
// Any subnodes added in viewDidLoad will then inherit the proper environment.
ASEnvironmentTraitCollection traitCollection = [self environmentTraitCollectionForUITraitCollection:self.traitCollection];
[self progagateNewEnvironmentTraitCollection:traitCollection];
ASPrimitiveTraitCollection traitCollection = [self primitiveTraitCollectionForUITraitCollection:self.traitCollection];
[self propagateNewTraitCollection:traitCollection];
}
- (void)viewWillLayoutSubviews
@ -112,13 +111,15 @@
// Before layout, make sure that our trait collection containerSize actually matches the size of our bounds.
// If not, we need to update the traits and propagate them.
CGSize boundsSize = self.view.bounds.size;
if (CGSizeEqualToSize(self.node.environmentTraitCollection.containerSize, boundsSize) == NO) {
if (CGSizeEqualToSize(self.node.primitiveTraitCollection.containerSize, boundsSize) == NO) {
[UIView performWithoutAnimation:^{
ASEnvironmentTraitCollection environmentTraitCollection = [self environmentTraitCollectionForUITraitCollection:self.traitCollection];
environmentTraitCollection.containerSize = boundsSize;
ASPrimitiveTraitCollection traitCollection = [self primitiveTraitCollectionForUITraitCollection:self.traitCollection];
traitCollection.containerSize = boundsSize;
// this method will call measure
[self progagateNewEnvironmentTraitCollection:environmentTraitCollection];
[self propagateNewTraitCollection:traitCollection];
}];
} else {
#pragma clang diagnostic push
@ -236,34 +237,33 @@ ASVisibilityDepthImplementation;
return _node.interfaceState;
}
#pragma mark - ASEnvironmentTraitCollection
#pragma mark - ASTraitEnvironment
- (ASEnvironmentTraitCollection)environmentTraitCollectionForUITraitCollection:(UITraitCollection *)traitCollection
- (ASPrimitiveTraitCollection)primitiveTraitCollectionForUITraitCollection:(UITraitCollection *)traitCollection
{
if (self.overrideDisplayTraitsWithTraitCollection) {
ASTraitCollection *asyncTraitCollection = self.overrideDisplayTraitsWithTraitCollection(traitCollection);
return [asyncTraitCollection environmentTraitCollection];
return [asyncTraitCollection primitiveTraitCollection];
}
ASDisplayNodeAssertMainThread();
ASEnvironmentTraitCollection asyncTraitCollection = ASEnvironmentTraitCollectionFromUITraitCollection(traitCollection);
ASPrimitiveTraitCollection asyncTraitCollection = ASPrimitiveTraitCollectionFromUITraitCollection(traitCollection);
asyncTraitCollection.containerSize = self.view.frame.size;
return asyncTraitCollection;
}
- (void)progagateNewEnvironmentTraitCollection:(ASEnvironmentTraitCollection)environmentTraitCollection
- (void)propagateNewTraitCollection:(ASPrimitiveTraitCollection)traitCollection
{
ASEnvironmentState environmentState = self.node.environmentState;
ASEnvironmentTraitCollection oldEnvironmentTraitCollection = environmentState.environmentTraitCollection;
ASPrimitiveTraitCollection oldTraitCollection = self.node.primitiveTraitCollection;
if (ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(environmentTraitCollection, oldEnvironmentTraitCollection) == NO) {
environmentState.environmentTraitCollection = environmentTraitCollection;
self.node.environmentState = environmentState;
if (ASPrimitiveTraitCollectionIsEqualToASPrimitiveTraitCollection(traitCollection, oldTraitCollection) == NO) {
self.node.primitiveTraitCollection = traitCollection;
NSArray<id<ASEnvironment>> *children = [self.node children];
for (id<ASEnvironment> child in children) {
ASEnvironmentStatePropagateDown(child, environmentState.environmentTraitCollection);
NSArray<id<ASLayoutElement>> *children = [self.node sublayoutElements];
for (id<ASLayoutElement> child in children) {
ASTraitCollectionPropagateDown(child, traitCollection);
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// Once we've propagated all the traits, layout this node.
@ -277,18 +277,18 @@ ASVisibilityDepthImplementation;
{
[super traitCollectionDidChange:previousTraitCollection];
ASEnvironmentTraitCollection environmentTraitCollection = [self environmentTraitCollectionForUITraitCollection:self.traitCollection];
environmentTraitCollection.containerSize = self.view.bounds.size;
[self progagateNewEnvironmentTraitCollection:environmentTraitCollection];
ASPrimitiveTraitCollection traitCollection = [self primitiveTraitCollectionForUITraitCollection:self.traitCollection];
traitCollection.containerSize = self.view.bounds.size;
[self propagateNewTraitCollection:traitCollection];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
ASEnvironmentTraitCollection traitCollection = self.node.environmentTraitCollection;
ASPrimitiveTraitCollection traitCollection = self.node.primitiveTraitCollection;
traitCollection.containerSize = self.view.bounds.size;
[self progagateNewEnvironmentTraitCollection:traitCollection];
[self propagateNewTraitCollection:traitCollection];
}
@end

View File

@ -60,7 +60,6 @@
#import <AsyncDisplayKit/ASDimension.h>
#import <AsyncDisplayKit/ASDimensionInternal.h>
#import <AsyncDisplayKit/ASDimensionDeprecated.h>
#import <AsyncDisplayKit/ASEnvironment.h>
#import <AsyncDisplayKit/ASLayoutElement.h>
#import <AsyncDisplayKit/ASLayoutSpec.h>
#import <AsyncDisplayKit/ASBackgroundLayoutSpec.h>

View File

@ -9,6 +9,10 @@
#pragma once
#import <AsyncDisplayKit/ASControlNode.h>
#define ASLAYOUTSPEC_DEBUG 1
#if ASLAYOUTSPEC_DEBUG
@class ASLayoutSpec;
@interface ASLayoutSpecVisualizerNode : ASControlNode
@ -19,3 +23,5 @@
@end
#endif

View File

@ -7,6 +7,9 @@
//
#import <AsyncDisplayKit/ASLayoutSpec+Debug.h>
#if ASLAYOUTSPEC_DEBUG
#import <AsyncDisplayKit/ASDisplayNode+Beta.h>
#import <AsyncDisplayKit/AsyncDisplayKit.h>
#import <AsyncDisplayKit/ASLayoutElementInspectorNode.h>
@ -71,3 +74,4 @@
@end
#endif

View File

@ -209,7 +209,7 @@
- (void)_populateSupplementaryNodesOfKind:(NSString *)kind withSections:(NSIndexSet *)sections mutableContexts:(NSMutableArray<ASIndexedNodeContext *> *)contexts
{
__weak id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
__weak id<ASTraitEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
[sections enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
for (NSUInteger sec = range.location; sec < NSMaxRange(range); sec++) {
@ -224,7 +224,7 @@
- (void)_populateSupplementaryNodesOfKind:(NSString *)kind atIndexPaths:(NSArray<NSIndexPath *> *)indexPaths mutableContexts:(NSMutableArray<ASIndexedNodeContext *> *)contexts
{
__weak id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
__weak id<ASTraitEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
NSMutableIndexSet *sections = [NSMutableIndexSet indexSet];
for (NSIndexPath *indexPath in indexPaths) {
@ -242,7 +242,7 @@
}];
}
- (void)_populateSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath mutableContexts:(NSMutableArray<ASIndexedNodeContext *> *)contexts environment:(id<ASEnvironment>)environment
- (void)_populateSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath mutableContexts:(NSMutableArray<ASIndexedNodeContext *> *)contexts environment:(id<ASTraitEnvironment>)environment
{
ASCellNodeBlock supplementaryCellBlock;
if (_dataSourceImplementsSupplementaryNodeBlockOfKindAtIndexPath) {

View File

@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN
@class ASCellNode;
@class ASDataController;
@class _ASHierarchyChangeSet;
@protocol ASEnvironment;
@protocol ASTraitEnvironment;
typedef NSUInteger ASDataControllerAnimationOptions;
@ -67,7 +67,7 @@ extern NSString * const ASCollectionInvalidUpdateException;
@end
@protocol ASDataControllerEnvironmentDelegate
- (id<ASEnvironment>)dataControllerEnvironment;
- (id<ASTraitEnvironment>)dataControllerEnvironment;
@end
/**

View File

@ -13,7 +13,6 @@
#import <AsyncDisplayKit/_ASHierarchyChangeSet.h>
#import <AsyncDisplayKit/ASAssert.h>
#import <AsyncDisplayKit/ASCellNode.h>
#import <AsyncDisplayKit/ASEnvironmentInternal.h>
#import <AsyncDisplayKit/ASLayout.h>
#import <AsyncDisplayKit/ASMainSerialQueue.h>
#import <AsyncDisplayKit/ASMultidimensionalArrayUtils.h>
@ -518,7 +517,7 @@ NSString * const ASCollectionInvalidUpdateException = @"ASCollectionInvalidUpdat
{
ASDisplayNodeAssertMainThread();
__weak id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
__weak id<ASTraitEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
std::vector<NSInteger> counts = [self itemCountsFromDataSource];
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
@ -807,7 +806,7 @@ NSString * const ASCollectionInvalidUpdateException = @"ASCollectionInvalidUpdat
NSArray *sortedIndexPaths = [indexPaths sortedArrayUsingSelector:@selector(compare:)];
NSMutableArray<ASIndexedNodeContext *> *contexts = [[NSMutableArray alloc] initWithCapacity:indexPaths.count];
__weak id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
__weak id<ASTraitEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
for (NSIndexPath *indexPath in sortedIndexPaths) {
ASCellNodeBlock nodeBlock = [_dataSource dataController:self nodeBlockAtIndexPath:indexPath];

View File

@ -1,166 +0,0 @@
//
// ASEnvironment.h
// AsyncDisplayKit
//
// 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>
#import <AsyncDisplayKit/ASBaseDefines.h>
#import <AsyncDisplayKit/ASDimension.h>
#import <AsyncDisplayKit/ASStackLayoutDefines.h>
@protocol ASEnvironment;
@class UITraitCollection;
ASDISPLAYNODE_EXTERN_C_BEGIN
NS_ASSUME_NONNULL_BEGIN
static const int kMaxEnvironmentStateBoolExtensions = 1;
static const int kMaxEnvironmentStateIntegerExtensions = 4;
static const int kMaxEnvironmentStateEdgeInsetExtensions = 1;
#pragma mark -
typedef struct ASEnvironmentStateExtensions {
// Values to store extensions
BOOL boolExtensions[kMaxEnvironmentStateBoolExtensions];
NSInteger integerExtensions[kMaxEnvironmentStateIntegerExtensions];
UIEdgeInsets edgeInsetsExtensions[kMaxEnvironmentStateEdgeInsetExtensions];
} ASEnvironmentStateExtensions;
#pragma mark - ASEnvironmentLayoutOptionsState
typedef struct ASEnvironmentLayoutOptionsState {
CGFloat spacingBefore;// = 0;
CGFloat spacingAfter;// = 0;
CGFloat flexGrow;// = 0;
CGFloat flexShrink;// = 0;
ASDimension flexBasis;// = ASDimensionAuto;
ASStackLayoutAlignSelf alignSelf;// = ASStackLayoutAlignSelfAuto;
CGFloat ascender;// = 0;
CGFloat descender;// = 0;
CGPoint layoutPosition;// = CGPointZero;
struct ASEnvironmentStateExtensions _extensions;
} ASEnvironmentLayoutOptionsState;
/// Should be used to create an ASEnvironmentLayoutOptionsState
extern ASEnvironmentLayoutOptionsState ASEnvironmentLayoutOptionsStateMakeDefault();
#pragma mark - ASEnvironmentHierarchyState
typedef struct ASEnvironmentHierarchyState {
unsigned rasterized:1; // = NO
unsigned rangeManaged:1; // = NO
unsigned transitioningSupernodes:1; // = NO
unsigned layoutPending:1; // = NO
} ASEnvironmentHierarchyState;
extern ASEnvironmentHierarchyState ASEnvironmentHierarchyStateMakeDefault();
#pragma mark - ASEnvironmentDisplayTraits
typedef struct ASEnvironmentTraitCollection {
CGFloat displayScale;
UIUserInterfaceSizeClass horizontalSizeClass;
UIUserInterfaceIdiom userInterfaceIdiom;
UIUserInterfaceSizeClass verticalSizeClass;
UIForceTouchCapability forceTouchCapability;
CGSize containerSize;
} ASEnvironmentTraitCollection;
extern ASEnvironmentTraitCollection ASEnvironmentTraitCollectionMakeDefault();
extern ASEnvironmentTraitCollection ASEnvironmentTraitCollectionFromUITraitCollection(UITraitCollection *traitCollection);
extern BOOL ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(ASEnvironmentTraitCollection lhs, ASEnvironmentTraitCollection rhs);
extern NSString *NSStringFromASEnvironmentTraitCollection(ASEnvironmentTraitCollection traits);
#pragma mark - ASEnvironmentState
typedef struct ASEnvironmentState {
struct ASEnvironmentHierarchyState hierarchyState;
struct ASEnvironmentLayoutOptionsState layoutOptionsState;
struct ASEnvironmentTraitCollection environmentTraitCollection;
} ASEnvironmentState;
extern ASEnvironmentState ASEnvironmentStateMakeDefault();
ASDISPLAYNODE_EXTERN_C_END
@class ASTraitCollection;
#pragma mark - ASEnvironment
/**
* ASEnvironment allows objects that conform to the ASEnvironment protocol to be able to propagate specific States
* defined in an ASEnvironmentState up and down the ASEnvironment tree. To be able to define how merges of
* States should happen, specific merge functions can be provided
*/
@protocol ASEnvironment <NSObject>
/// The environment collection of an object which class conforms to the ASEnvironment protocol
- (ASEnvironmentState)environmentState;
- (void)setEnvironmentState:(ASEnvironmentState)environmentState;
/// Returns the parent of an object which class conforms to the ASEnvironment protocol
- (nullable id<ASEnvironment>)parent;
/// Returns all children of an object which class conforms to the ASEnvironment protocol
- (nullable NSArray<id<ASEnvironment>> *)children;
/// Classes should implement this method and return YES / NO dependent if upward propagation is enabled or not
// Currently this is disabled as propagation of any attributions besides trait collections is not supported at the moment
// - (BOOL)supportsUpwardPropagation;
/// Classes should implement this method and return YES / NO dependent if downware propagation is enabled or not
- (BOOL)supportsTraitsCollectionPropagation;
/// Returns an NSObject-representation of the environment's ASEnvironmentDisplayTraits
- (ASTraitCollection *)asyncTraitCollection;
/// Returns a struct-representation of the environment's ASEnvironmentDisplayTraits. This only exists as a internal
/// convenience method. Users should access the trait collections through the NSObject based asyncTraitCollection API
- (ASEnvironmentTraitCollection)environmentTraitCollection;
/// sets a trait collection on this environment state.
- (void)setEnvironmentTraitCollection:(ASEnvironmentTraitCollection)environmentTraitCollection;
@end
// ASCollection/TableNodes don't actually have ASCellNodes as subnodes. Because of this we can't rely on display trait
// downward propagation via ASEnvironment. Instead if the new environmentState has displayTraits that are different from
// the cells', then we propagate downward explicitly and request a relayout.
//
// If there is any new downward propagating state, it should be added to this define.
//
// If the only change in a trait collection is that its dislplayContext has gone from non-nil to nil,
// assume that we are clearing the context as part of a ASVC dealloc and do not trigger a layout.
//
// This logic is used in both ASCollectionNode and ASTableNode
#define ASEnvironmentCollectionTableSetEnvironmentState(lock) \
- (void)setEnvironmentState:(ASEnvironmentState)environmentState\
{\
ASDN::MutexLocker l(lock);\
ASEnvironmentTraitCollection oldTraits = self.environmentState.environmentTraitCollection;\
[super setEnvironmentState:environmentState];\
\
/* Extra Trait Collection Handling */\
/* If the node is not loaded yet don't do anything as otherwise the access of the view will trigger a load*/\
if (!self.isNodeLoaded) { return; } \
ASEnvironmentTraitCollection currentTraits = environmentState.environmentTraitCollection;\
if (ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(currentTraits, oldTraits) == NO) {\
/* Must dispatch to main for self.view && [self.view.dataController completedNodes]*/ \
ASPerformBlockOnMainThread(^{\
NSArray<NSArray <ASCellNode *> *> *completedNodes = [self.view.dataController completedNodes];\
for (NSArray *sectionArray in completedNodes) {\
for (ASCellNode *cellNode in sectionArray) {\
ASEnvironmentStatePropagateDown(cellNode, currentTraits);\
}\
}\
});\
}\
}\
NS_ASSUME_NONNULL_END

View File

@ -1,121 +0,0 @@
//
// ASEnvironment.mm
// AsyncDisplayKit
//
// 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/ASEnvironmentInternal.h>
#import <AsyncDisplayKit/ASAvailability.h>
#import <AsyncDisplayKit/ASObjectDescriptionHelpers.h>
ASEnvironmentLayoutOptionsState ASEnvironmentLayoutOptionsStateMakeDefault()
{
return (ASEnvironmentLayoutOptionsState) {
// Default values can be defined in here
};
}
ASEnvironmentHierarchyState ASEnvironmentHierarchyStateMakeDefault()
{
return (ASEnvironmentHierarchyState) {
// Default values can be defined in here
};
}
ASEnvironmentTraitCollection ASEnvironmentTraitCollectionMakeDefault()
{
return (ASEnvironmentTraitCollection) {
// Default values can be defined in here
.userInterfaceIdiom = UIUserInterfaceIdiomUnspecified,
.containerSize = CGSizeZero,
};
}
ASEnvironmentTraitCollection ASEnvironmentTraitCollectionFromUITraitCollection(UITraitCollection *traitCollection)
{
ASEnvironmentTraitCollection environmentTraitCollection = ASEnvironmentTraitCollectionMakeDefault();
environmentTraitCollection.displayScale = traitCollection.displayScale;
environmentTraitCollection.horizontalSizeClass = traitCollection.horizontalSizeClass;
environmentTraitCollection.verticalSizeClass = traitCollection.verticalSizeClass;
environmentTraitCollection.userInterfaceIdiom = traitCollection.userInterfaceIdiom;
if (AS_AT_LEAST_IOS9) {
environmentTraitCollection.forceTouchCapability = traitCollection.forceTouchCapability;
}
return environmentTraitCollection;
}
BOOL ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(ASEnvironmentTraitCollection lhs, ASEnvironmentTraitCollection rhs)
{
return
lhs.verticalSizeClass == rhs.verticalSizeClass &&
lhs.horizontalSizeClass == rhs.horizontalSizeClass &&
lhs.displayScale == rhs.displayScale &&
lhs.userInterfaceIdiom == rhs.userInterfaceIdiom &&
lhs.forceTouchCapability == rhs.forceTouchCapability &&
CGSizeEqualToSize(lhs.containerSize, rhs.containerSize);
}
// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline
ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIUserInterfaceIdiom(UIUserInterfaceIdiom idiom) {
switch (idiom) {
case UIUserInterfaceIdiomTV:
return @"TV";
case UIUserInterfaceIdiomPad:
return @"Pad";
case UIUserInterfaceIdiomPhone:
return @"Phone";
case UIUserInterfaceIdiomCarPlay:
return @"CarPlay";
default:
return @"Unspecified";
}
}
// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline
ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIForceTouchCapability(UIForceTouchCapability capability) {
switch (capability) {
case UIForceTouchCapabilityAvailable:
return @"Available";
case UIForceTouchCapabilityUnavailable:
return @"Unavailable";
default:
return @"Unknown";
}
}
// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline
ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIUserInterfaceSizeClass(UIUserInterfaceSizeClass sizeClass) {
switch (sizeClass) {
case UIUserInterfaceSizeClassCompact:
return @"Compact";
case UIUserInterfaceSizeClassRegular:
return @"Regular";
default:
return @"Unspecified";
}
}
NSString *NSStringFromASEnvironmentTraitCollection(ASEnvironmentTraitCollection traits)
{
NSMutableArray<NSDictionary *> *props = [NSMutableArray array];
[props addObject:@{ @"userInterfaceIdiom": AS_NSStringFromUIUserInterfaceIdiom(traits.userInterfaceIdiom) }];
[props addObject:@{ @"containerSize": NSStringFromCGSize(traits.containerSize) }];
[props addObject:@{ @"horizontalSizeClass": AS_NSStringFromUIUserInterfaceSizeClass(traits.horizontalSizeClass) }];
[props addObject:@{ @"verticalSizeClass": AS_NSStringFromUIUserInterfaceSizeClass(traits.verticalSizeClass) }];
[props addObject:@{ @"forceTouchCapability": AS_NSStringFromUIForceTouchCapability(traits.forceTouchCapability) }];
return ASObjectDescriptionMakeWithoutObject(props);
}
ASEnvironmentState ASEnvironmentStateMakeDefault()
{
return (ASEnvironmentState) {
.layoutOptionsState = ASEnvironmentLayoutOptionsStateMakeDefault(),
.hierarchyState = ASEnvironmentHierarchyStateMakeDefault(),
.environmentTraitCollection = ASEnvironmentTraitCollectionMakeDefault()
};
}

View File

@ -11,7 +11,7 @@
//
#import <AsyncDisplayKit/ASDataController.h>
#import <AsyncDisplayKit/ASEnvironment.h>
#import <AsyncDisplayKit/ASTraitCollection.h>
NS_ASSUME_NONNULL_BEGIN
@ -24,13 +24,13 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly, strong) NSIndexPath *indexPath;
@property (nonatomic, readonly, copy, nullable) NSString *supplementaryElementKind;
@property (nonatomic, readonly, assign) ASSizeRange constrainedSize;
@property (weak, nonatomic) id<ASEnvironment> environment;
@property (weak, nonatomic) id<ASTraitEnvironment> traitEnvironment;
- (instancetype)initWithNodeBlock:(ASCellNodeBlock)nodeBlock
indexPath:(NSIndexPath *)indexPath
supplementaryElementKind:(nullable NSString *)supplementaryElementKind
constrainedSize:(ASSizeRange)constrainedSize
environment:(id<ASEnvironment>)environment;
environment:(id<ASTraitEnvironment>)environment;
/**
* @return The node, running the node block if necessary. The node block will be discarded

View File

@ -11,7 +11,6 @@
//
#import <AsyncDisplayKit/ASIndexedNodeContext.h>
#import <AsyncDisplayKit/ASEnvironmentInternal.h>
#import <AsyncDisplayKit/ASCellNode+Internal.h>
#import <mutex>
@ -31,7 +30,7 @@
indexPath:(NSIndexPath *)indexPath
supplementaryElementKind:(nullable NSString *)supplementaryElementKind
constrainedSize:(ASSizeRange)constrainedSize
environment:(id<ASEnvironment>)environment
environment:(id<ASTraitEnvironment>)environment
{
NSAssert(nodeBlock != nil && indexPath != nil, @"Node block and index path must not be nil");
self = [super init];
@ -40,7 +39,7 @@
_indexPath = indexPath;
_supplementaryElementKind = [supplementaryElementKind copy];
_constrainedSize = constrainedSize;
_environment = environment;
_traitEnvironment = environment;
}
return self;
}
@ -57,8 +56,8 @@
}
node.cachedIndexPath = _indexPath;
node.supplementaryElementKind = _supplementaryElementKind;
node.owningNode = (ASDisplayNode *)_environment;
ASEnvironmentStatePropagateDown(node, [_environment environmentTraitCollection]);
node.owningNode = (ASDisplayNode *)_traitEnvironment;
ASTraitCollectionPropagateDown(node, [_traitEnvironment primitiveTraitCollection]);
_node = node;
}
return _node;

View File

@ -6,8 +6,15 @@
// Copyright © 2016 Facebook. All rights reserved.
//
#import <AsyncDisplayKit/ASAvailability.h>
#import <AsyncDisplayKit/ASObjectDescriptionHelpers.h>
#import <UIKit/UIKit.h>
#if AS_TARGET_OS_IOS
#import <UIKit/UIGeometry.h>
#else
#import <Foundation/NSGeometry.h>
#endif
#import <AsyncDisplayKit/NSIndexSet+ASHelpers.h>
NSString *ASGetDescriptionValueString(id object)
@ -16,6 +23,7 @@ NSString *ASGetDescriptionValueString(id object)
// Use shortened NSValue descriptions
NSValue *value = object;
const char *type = value.objCType;
if (strcmp(type, @encode(CGRect)) == 0) {
CGRect rect = [value CGRectValue];
return [NSString stringWithFormat:@"(%g %g; %g %g)", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height];
@ -24,6 +32,7 @@ NSString *ASGetDescriptionValueString(id object)
} else if (strcmp(type, @encode(CGPoint)) == 0) {
return NSStringFromCGPoint(value.CGPointValue);
}
} else if ([object isKindOfClass:[NSIndexSet class]]) {
return [object as_smallDescription];
} else if ([object isKindOfClass:[NSIndexPath class]]) {

View File

@ -8,12 +8,134 @@
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <AsyncDisplayKit/ASAvailability.h>
#if AS_TARGET_OS_IOS
#import <UIKit/UIKit.h>
#import <AsyncDisplayKit/ASEnvironment.h>
#import <AsyncDisplayKit/ASBaseDefines.h>
@class ASTraitCollection;
@protocol ASLayoutElement;
NS_ASSUME_NONNULL_BEGIN
ASDISPLAYNODE_EXTERN_C_BEGIN
#pragma mark - ASPrimitiveTraitCollection
typedef struct ASPrimitiveTraitCollection {
CGFloat displayScale;
UIUserInterfaceSizeClass horizontalSizeClass;
UIUserInterfaceIdiom userInterfaceIdiom;
UIUserInterfaceSizeClass verticalSizeClass;
UIForceTouchCapability forceTouchCapability;
CGSize containerSize;
} ASPrimitiveTraitCollection;
/**
* Creates ASPrimitiveTraitCollection with default values.
*/
extern ASPrimitiveTraitCollection ASPrimitiveTraitCollectionMakeDefault();
/**
* Creates a ASPrimitiveTraitCollection from a given UITraitCollection.
*/
extern ASPrimitiveTraitCollection ASPrimitiveTraitCollectionFromUITraitCollection(UITraitCollection *traitCollection);
/**
* Compares two ASPrimitiveTraitCollection to determine if they are the same.
*/
extern BOOL ASPrimitiveTraitCollectionIsEqualToASPrimitiveTraitCollection(ASPrimitiveTraitCollection lhs, ASPrimitiveTraitCollection rhs);
/**
* Returns a string representation of a ASPrimitiveTraitCollection.
*/
extern NSString *NSStringFromASPrimitiveTraitCollection(ASPrimitiveTraitCollection traits);
/**
* This function will walk the layout element hierarchy and updates the layout element trait collection for every
* layout element within the hierarchy.
*/
extern void ASTraitCollectionPropagateDown(id<ASLayoutElement> root, ASPrimitiveTraitCollection traitCollection);
/// For backward compatibility reasons we redefine the old layout element trait collection struct name
#define ASEnvironmentTraitCollection ASPrimitiveTraitCollection
#define ASEnvironmentTraitCollectionMakeDefault ASPrimitiveTraitCollectionMakeDefault
ASDISPLAYNODE_EXTERN_C_END
/**
* Abstraction on top of UITraitCollection for propagation within AsyncDisplayKit-Layout
*/
@protocol ASTraitEnvironment <NSObject>
/**
* Returns a struct-representation of the environment's ASEnvironmentDisplayTraits. This only exists as a internal
* convenience method. Users should access the trait collections through the NSObject based asyncTraitCollection API
*/
- (ASPrimitiveTraitCollection)primitiveTraitCollection;
/**
* Sets a trait collection on this environment state.
*/
- (void)setPrimitiveTraitCollection:(ASPrimitiveTraitCollection)traitCollection;
/**
* Returns an NSObject-representation of the environment's ASEnvironmentDisplayTraits
*/
- (ASTraitCollection *)asyncTraitCollection;
/**
* Deprecated and should be replaced by the methods from above
*/
- (ASEnvironmentTraitCollection)environmentTraitCollection;
- (void)setEnvironmentTraitCollection:(ASEnvironmentTraitCollection)traitCollection;;
@end
#define ASPrimitiveTraitCollectionDeprecatedImplementation \
- (ASEnvironmentTraitCollection)environmentTraitCollection\
{\
return self.primitiveTraitCollection;\
}\
- (void)setEnvironmentTraitCollection:(ASEnvironmentTraitCollection)traitCollection\
{\
[self setPrimitiveTraitCollection:traitCollection];\
}\
#define ASLayoutElementCollectionTableSetTraitCollection(lock) \
- (void)setPrimitiveTraitCollection:(ASPrimitiveTraitCollection)traitCollection\
{\
ASDN::MutexLocker l(lock);\
\
ASPrimitiveTraitCollection oldTraits = self.primitiveTraitCollection;\
[super setPrimitiveTraitCollection:traitCollection];\
\
/* Extra Trait Collection Handling */\
\
/* If the node is not loaded yet don't do anything as otherwise the access of the view will trigger a load*/\
if (!self.isNodeLoaded) { return; }\
\
ASPrimitiveTraitCollection currentTraits = self.primitiveTraitCollection;\
if (ASPrimitiveTraitCollectionIsEqualToASPrimitiveTraitCollection(currentTraits, oldTraits) == NO) {\
/* Must dispatch to main for self.view && [self.view.dataController completedNodes]*/\
ASPerformBlockOnMainThread(^{\
NSArray<NSArray <ASCellNode *> *> *completedNodes = [self.view.dataController completedNodes];\
for (NSArray *sectionArray in completedNodes) {\
for (ASCellNode *cellNode in sectionArray) {\
ASTraitCollectionPropagateDown(cellNode, currentTraits);\
}\
}\
});\
}\
}\
#pragma mark - ASTraitCollection
AS_SUBCLASSING_RESTRICTED
@interface ASTraitCollection : NSObject
@ -24,7 +146,7 @@ AS_SUBCLASSING_RESTRICTED
@property (nonatomic, assign, readonly) UIForceTouchCapability forceTouchCapability;
@property (nonatomic, assign, readonly) CGSize containerSize;
+ (ASTraitCollection *)traitCollectionWithASEnvironmentTraitCollection:(ASEnvironmentTraitCollection)traits;
+ (ASTraitCollection *)traitCollectionWithASPrimitiveTraitCollection:(ASPrimitiveTraitCollection)traits;
+ (ASTraitCollection *)traitCollectionWithUITraitCollection:(UITraitCollection *)traitCollection
containerSize:(CGSize)windowSize;
@ -35,12 +157,18 @@ AS_SUBCLASSING_RESTRICTED
horizontalSizeClass:(UIUserInterfaceSizeClass)horizontalSizeClass
verticalSizeClass:(UIUserInterfaceSizeClass)verticalSizeClass
forceTouchCapability:(UIForceTouchCapability)forceTouchCapability
containerSize:(CGSize)windowSize;
containerSize:(CGSize)windowSize;
- (ASEnvironmentTraitCollection)environmentTraitCollection;
- (ASPrimitiveTraitCollection)primitiveTraitCollection;
- (BOOL)isEqualToTraitCollection:(ASTraitCollection *)traitCollection;
@end
NS_ASSUME_NONNULL_END
#else
// Non iOS
#endif

View File

@ -11,7 +11,105 @@
//
#import <AsyncDisplayKit/ASTraitCollection.h>
#import <AsyncDisplayKit/ASAvailability.h>
#if AS_TARGET_OS_IOS
#import <AsyncDisplayKit/ASObjectDescriptionHelpers.h>
#import <AsyncDisplayKit/ASLayoutElement.h>
#pragma mark - ASPrimitiveTraitCollection
extern void ASTraitCollectionPropagateDown(id<ASLayoutElement> root, ASPrimitiveTraitCollection traitCollection) {
ASLayoutElementPerformBlockOnEveryElement(root, ^(id<ASLayoutElement> _Nonnull element) {
element.primitiveTraitCollection = traitCollection;
});
}
ASPrimitiveTraitCollection ASPrimitiveTraitCollectionMakeDefault()
{
return (ASPrimitiveTraitCollection) {
// Default values can be defined in here
.userInterfaceIdiom = UIUserInterfaceIdiomUnspecified,
.containerSize = CGSizeZero,
};
}
ASPrimitiveTraitCollection ASPrimitiveTraitCollectionFromUITraitCollection(UITraitCollection *traitCollection)
{
ASPrimitiveTraitCollection environmentTraitCollection = ASPrimitiveTraitCollectionMakeDefault();
environmentTraitCollection.displayScale = traitCollection.displayScale;
environmentTraitCollection.horizontalSizeClass = traitCollection.horizontalSizeClass;
environmentTraitCollection.verticalSizeClass = traitCollection.verticalSizeClass;
environmentTraitCollection.userInterfaceIdiom = traitCollection.userInterfaceIdiom;
if (AS_AT_LEAST_IOS9) {
environmentTraitCollection.forceTouchCapability = traitCollection.forceTouchCapability;
}
return environmentTraitCollection;
}
BOOL ASPrimitiveTraitCollectionIsEqualToASPrimitiveTraitCollection(ASPrimitiveTraitCollection lhs, ASPrimitiveTraitCollection rhs)
{
return
lhs.verticalSizeClass == rhs.verticalSizeClass &&
lhs.horizontalSizeClass == rhs.horizontalSizeClass &&
lhs.displayScale == rhs.displayScale &&
lhs.userInterfaceIdiom == rhs.userInterfaceIdiom &&
lhs.forceTouchCapability == rhs.forceTouchCapability &&
CGSizeEqualToSize(lhs.containerSize, rhs.containerSize);
}
// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline
ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIUserInterfaceIdiom(UIUserInterfaceIdiom idiom) {
switch (idiom) {
case UIUserInterfaceIdiomTV:
return @"TV";
case UIUserInterfaceIdiomPad:
return @"Pad";
case UIUserInterfaceIdiomPhone:
return @"Phone";
case UIUserInterfaceIdiomCarPlay:
return @"CarPlay";
default:
return @"Unspecified";
}
}
// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline
ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIForceTouchCapability(UIForceTouchCapability capability) {
switch (capability) {
case UIForceTouchCapabilityAvailable:
return @"Available";
case UIForceTouchCapabilityUnavailable:
return @"Unavailable";
default:
return @"Unknown";
}
}
// Named so as not to conflict with a hidden Apple function, in case compiler decides not to inline
ASDISPLAYNODE_INLINE NSString *AS_NSStringFromUIUserInterfaceSizeClass(UIUserInterfaceSizeClass sizeClass) {
switch (sizeClass) {
case UIUserInterfaceSizeClassCompact:
return @"Compact";
case UIUserInterfaceSizeClassRegular:
return @"Regular";
default:
return @"Unspecified";
}
}
NSString *NSStringFromASPrimitiveTraitCollection(ASPrimitiveTraitCollection traits)
{
NSMutableArray<NSDictionary *> *props = [NSMutableArray array];
[props addObject:@{ @"userInterfaceIdiom": AS_NSStringFromUIUserInterfaceIdiom(traits.userInterfaceIdiom) }];
[props addObject:@{ @"containerSize": NSStringFromCGSize(traits.containerSize) }];
[props addObject:@{ @"horizontalSizeClass": AS_NSStringFromUIUserInterfaceSizeClass(traits.horizontalSizeClass) }];
[props addObject:@{ @"verticalSizeClass": AS_NSStringFromUIUserInterfaceSizeClass(traits.verticalSizeClass) }];
[props addObject:@{ @"forceTouchCapability": AS_NSStringFromUIForceTouchCapability(traits.forceTouchCapability) }];
return ASObjectDescriptionMakeWithoutObject(props);
}
#pragma mark - ASTraitCollection
@implementation ASTraitCollection
@ -49,7 +147,7 @@
containerSize:windowSize];
}
+ (instancetype)traitCollectionWithASEnvironmentTraitCollection:(ASEnvironmentTraitCollection)traits
+ (instancetype)traitCollectionWithASPrimitiveTraitCollection:(ASPrimitiveTraitCollection)traits
{
return [self traitCollectionWithDisplayScale:traits.displayScale
userInterfaceIdiom:traits.userInterfaceIdiom
@ -71,9 +169,9 @@
containerSize:windowSize];
}
- (ASEnvironmentTraitCollection)environmentTraitCollection
- (ASPrimitiveTraitCollection)primitiveTraitCollection
{
return (ASEnvironmentTraitCollection) {
return (ASPrimitiveTraitCollection) {
.displayScale = self.displayScale,
.horizontalSizeClass = self.horizontalSizeClass,
.userInterfaceIdiom = self.userInterfaceIdiom,
@ -98,3 +196,9 @@
}
@end
#else
// Non iOS
#endif

View File

@ -6,7 +6,13 @@
// Copyright © 2016 Facebook. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <AsyncDisplayKit/ASAvailability.h>
#if AS_TARGET_OS_IOS
#import <UIKit/UIKit.h>
#else
#import <Cocoa/Cocoa.h>
#endif
#import <AsyncDisplayKit/NSIndexSet+ASHelpers.h>

View File

@ -9,7 +9,8 @@
//
#import <AsyncDisplayKit/ASAsciiArtBoxCreator.h>
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>
#import <tgmath.h>
static const NSUInteger kDebugBoxPadding = 2;

View File

@ -9,8 +9,8 @@
//
#pragma once
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <AsyncDisplayKit/ASBaseDefines.h>
#import <AsyncDisplayKit/ASAssert.h>

View File

@ -10,6 +10,12 @@
#import <AsyncDisplayKit/ASDimension.h>
#if AS_TARGET_OS_IOS
#import <UIKit/UIGeometry.h>
#else
#import <Foundation/NSGeometry.h>
#endif
#import <AsyncDisplayKit/CoreGraphics+ASConvenience.h>
#import <AsyncDisplayKit/ASAssert.h>
@ -99,7 +105,13 @@ ASSizeRange ASSizeRangeIntersect(ASSizeRange sizeRange, ASSizeRange otherSizeRan
NSString *NSStringFromASSizeRange(ASSizeRange sizeRange)
{
#if AS_TARGET_OS_IOS
return [NSString stringWithFormat:@"<ASSizeRange: min=%@, max=%@>",
NSStringFromCGSize(sizeRange.min),
NSStringFromCGSize(sizeRange.max)];
#else
return [NSString stringWithFormat:@"<ASSizeRange: min=%@, max=%@>",
NSStringFromRect(NSRectFromCGRect(sizeRange.min)),
NSStringFromRect(NSRectFromCGRect(sizeRange.max))];
#endif
}

View File

@ -8,6 +8,7 @@
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <AsyncDisplayKit/ASAvailability.h>
#import <AsyncDisplayKit/ASLayoutSpec.h>
NS_ASSUME_NONNULL_BEGIN

View File

@ -9,14 +9,10 @@
//
#pragma once
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <AsyncDisplayKit/ASDimension.h>
#import <AsyncDisplayKit/ASLayoutElement.h>
//#import <AsyncDisplayKit/ASAssert.h>
NS_ASSUME_NONNULL_BEGIN
ASDISPLAYNODE_EXTERN_C_BEGIN
@ -34,11 +30,11 @@ extern ASLayout *ASCalculateRootLayout(id<ASLayoutElement> rootLayoutElement, co
/**
* Safely computes the layout of the given node by guarding against nil nodes.
* @param layoutElement The component to calculate the layout for.
* @param layoutElement The layout element to calculate the layout for.
* @param sizeRange The size range to calculate the node layout within.
* @param parentSize The parent size of the node to calculate the layout for.
*/
extern ASLayout *ASCalculateLayout(id<ASLayoutElement> layoutElement, const ASSizeRange sizeRange, const CGSize parentSize);
extern ASLayout *ASCalculateLayout(id<ASLayoutElement>layoutElement, const ASSizeRange sizeRange, const CGSize parentSize);
ASDISPLAYNODE_EXTERN_C_END

View File

@ -8,6 +8,8 @@
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <AsyncDisplayKit/ASLayout.h>
#import <queue>
#import <AsyncDisplayKit/ASDimension.h>
@ -319,4 +321,3 @@ ASLayout *ASCalculateRootLayout(id<ASLayoutElement> rootLayoutElement, const ASS
// Here could specific verfication happen
return layout;
}

View File

@ -8,19 +8,24 @@
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <AsyncDisplayKit/ASAvailability.h>
#import <AsyncDisplayKit/ASLayoutElementPrivate.h>
#import <AsyncDisplayKit/ASLayoutElementExtensibility.h>
#import <AsyncDisplayKit/ASDimensionInternal.h>
#import <AsyncDisplayKit/ASStackLayoutDefines.h>
#import <AsyncDisplayKit/ASStackLayoutElement.h>
#import <AsyncDisplayKit/ASAbsoluteLayoutElement.h>
#import <AsyncDisplayKit/ASEnvironment.h>
@class ASLayout;
@class ASLayoutSpec;
@protocol ASLayoutElementStylability;
#if AS_TARGET_OS_IOS
#import "ASTraitCollection.h"
@protocol ASTraitEnvironment;
#endif
NS_ASSUME_NONNULL_BEGIN
/** A constant that indicates that the parent's size is not yet determined in a given dimension. */
extern CGFloat const ASLayoutElementParentDimensionUndefined;
@ -33,9 +38,19 @@ typedef NS_ENUM(NSUInteger, ASLayoutElementType) {
ASLayoutElementTypeDisplayNode
};
NS_ASSUME_NONNULL_BEGIN
ASDISPLAYNODE_EXTERN_C_BEGIN
/**
/**
This function will walk the layout element hierarchy. It does run the block on the node provided
directly to the function call.
*/
extern void ASLayoutElementPerformBlockOnEveryElement(id<ASLayoutElement> root, void(^block)(id<ASLayoutElement> element));
ASDISPLAYNODE_EXTERN_C_END
#pragma mark - ASLayoutElement
/**
* The ASLayoutElement protocol declares a method for measuring the layout of an object. A layout
* is defined by an ASLayout return value, and must specify 1) the size (but not position) of the
* layoutElement object, and 2) the size and position of all of its immediate child objects. The tree
@ -51,19 +66,18 @@ NS_ASSUME_NONNULL_BEGIN
* access to the options via convenience properties. If you are creating custom layout spec, then you can
* extend the backing layout options class to accommodate any new layout options.
*/
@protocol ASLayoutElement <ASEnvironment, ASLayoutElementPrivate, ASLayoutElementExtensibility, ASLayoutElementStylability, NSFastEnumeration>
#if AS_TARGET_OS_IOS
@protocol ASLayoutElement <ASLayoutElementExtensibility, ASLayoutElementFinalLayoutElement, ASTraitEnvironment>
#else
@protocol ASLayoutElement <ASLayoutElementExtensibility, ASLayoutElementFinalLayoutElement>
#endif
#pragma mark - Getter
/**
* @abstract Returns type of layoutElement
*/
@property (nonatomic, assign, readonly) ASLayoutElementType layoutElementType;
/**
* @abstract Returns if the layoutElement can be used to layout in an asynchronous way on a background thread.
*/
@property (nonatomic, assign, readonly) BOOL canLayoutAsynchronous;
@property (nonatomic, assign, readonly) ASLayoutElementType layoutElementType;;
/**
* @abstract A size constraint that should apply to this ASLayoutElement.
@ -71,7 +85,12 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign, readonly) ASLayoutElementStyle *style;
/**
* @abstract Optional name that is printed by ascii art string and displayed in description.
* @abstract Returns all children of an object which class conforms to the ASLayoutElement protocol
*/
- (nullable NSArray<id<ASLayoutElement>> *)sublayoutElements;
/**
* @abstract Optional name that is printed by ascii art string and displayed in description.
*/
@property (nullable, nonatomic, copy) NSString *debugName;
@ -157,6 +176,8 @@ NS_ASSUME_NONNULL_BEGIN
@end
#pragma mark - ASLayoutElementStyle
extern NSString * const ASLayoutElementStyleWidthProperty;
extern NSString * const ASLayoutElementStyleMinWidthProperty;
extern NSString * const ASLayoutElementStyleMaxWidthProperty;
@ -176,13 +197,11 @@ extern NSString * const ASLayoutElementStyleDescenderProperty;
extern NSString * const ASLayoutElementStyleLayoutPositionProperty;
#pragma mark - ASLayoutElementStyle
@protocol ASLayoutElementStyleDelegate <NSObject>
- (void)style:(__kindof ASLayoutElementStyle *)style propertyDidChange:(NSString *)propertyName;
@end
@interface ASLayoutElementStyle : NSObject <ASStackLayoutElement, ASAbsoluteLayoutElement>
@interface ASLayoutElementStyle : NSObject <ASStackLayoutElement, ASAbsoluteLayoutElement, ASLayoutElementExtensibility>
/**
* @abstract Initializes the layoutElement style with a specified delegate

View File

@ -10,12 +10,27 @@
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
#import <AsyncDisplayKit/ASLayoutElement.h>
#import <map>
#import <atomic>
#import <AsyncDisplayKit/ASThread.h>
#import <AsyncDisplayKit/ASObjectDescriptionHelpers.h>
extern void ASLayoutElementPerformBlockOnEveryElement(id<ASLayoutElement> element, void(^block)(id<ASLayoutElement> element))
{
if (element) {
block(element);
}
for (id<ASLayoutElement> subelement in element.sublayoutElements) {
ASLayoutElementPerformBlockOnEveryElement(subelement, block);
}
}
#pragma mark - ASLayoutElementContext
CGFloat const ASLayoutElementParentDimensionUndefined = NAN;
CGSize const ASLayoutElementParentSizeUndefined = {ASLayoutElementParentDimensionUndefined, ASLayoutElementParentDimensionUndefined};
@ -112,6 +127,7 @@ do {\
@implementation ASLayoutElementStyle {
ASDN::RecursiveMutex __instanceLock__;
ASLayoutElementSize _size;
ASLayoutElementStyleExtensions _extensions;
std::atomic<CGFloat> _spacingBefore;
std::atomic<CGFloat> _spacingAfter;
@ -438,6 +454,56 @@ do {\
return _layoutPosition.load();
}
#pragma mark - Extensions
- (void)setLayoutOptionExtensionBool:(BOOL)value atIndex:(int)idx
{
NSCAssert(idx < kMaxLayoutElementBoolExtensions, @"Setting index outside of max bool extensions space");
ASDN::MutexLocker l(__instanceLock__);
_extensions.boolExtensions[idx] = value;
}
- (BOOL)layoutOptionExtensionBoolAtIndex:(int)idx\
{
NSCAssert(idx < kMaxLayoutElementBoolExtensions, @"Accessing index outside of max bool extensions space");
ASDN::MutexLocker l(__instanceLock__);
return _extensions.boolExtensions[idx];
}
- (void)setLayoutOptionExtensionInteger:(NSInteger)value atIndex:(int)idx
{
NSCAssert(idx < kMaxLayoutElementStateIntegerExtensions, @"Setting index outside of max integer extensions space");
ASDN::MutexLocker l(__instanceLock__);
_extensions.integerExtensions[idx] = value;
}
- (NSInteger)layoutOptionExtensionIntegerAtIndex:(int)idx
{
NSCAssert(idx < kMaxLayoutElementStateIntegerExtensions, @"Accessing index outside of max integer extensions space");
ASDN::MutexLocker l(__instanceLock__);
return _extensions.integerExtensions[idx];
}
- (void)setLayoutOptionExtensionEdgeInsets:(UIEdgeInsets)value atIndex:(int)idx
{
NSCAssert(idx < kMaxLayoutElementStateEdgeInsetExtensions, @"Setting index outside of max edge insets extensions space");
ASDN::MutexLocker l(__instanceLock__);
_extensions.edgeInsetsExtensions[idx] = value;
}
- (UIEdgeInsets)layoutOptionExtensionEdgeInsetsAtIndex:(int)idx
{
NSCAssert(idx < kMaxLayoutElementStateEdgeInsetExtensions, @"Accessing index outside of max edge insets extensions space");
ASDN::MutexLocker l(__instanceLock__);
return _extensions.edgeInsetsExtensions[idx];
}
#pragma mark - Debugging
- (NSString *)description
@ -464,9 +530,7 @@ do {\
[result addObject:@{ @"maxLayoutSize" : NSStringFromASLayoutSize(self.maxLayoutSize) }];
}
const ASEnvironmentLayoutOptionsState defaultState = ASEnvironmentLayoutOptionsStateMakeDefault();
if (self.alignSelf != defaultState.alignSelf) {
if (self.alignSelf != ASStackLayoutAlignSelfAuto) {
[result addObject:@{ @"alignSelf" : [@[@"ASStackLayoutAlignSelfAuto",
@"ASStackLayoutAlignSelfStart",
@"ASStackLayoutAlignSelfEnd",
@ -474,35 +538,35 @@ do {\
@"ASStackLayoutAlignSelfStretch"] objectAtIndex:self.alignSelf] }];
}
if (self.ascender != defaultState.ascender) {
if (self.ascender != 0) {
[result addObject:@{ @"ascender" : @(self.ascender) }];
}
if (self.descender != defaultState.descender) {
if (self.descender != 0) {
[result addObject:@{ @"descender" : @(self.descender) }];
}
if (ASDimensionEqualToDimension(self.flexBasis, defaultState.flexBasis) == NO) {
if (ASDimensionEqualToDimension(self.flexBasis, ASDimensionAuto) == NO) {
[result addObject:@{ @"flexBasis" : NSStringFromASDimension(self.flexBasis) }];
}
if (self.flexGrow != defaultState.flexGrow) {
if (self.flexGrow != 0) {
[result addObject:@{ @"flexGrow" : @(self.flexGrow) }];
}
if (self.flexShrink != defaultState.flexShrink) {
if (self.flexShrink != 0) {
[result addObject:@{ @"flexShrink" : @(self.flexShrink) }];
}
if (self.spacingAfter != defaultState.spacingAfter) {
if (self.spacingAfter != 0) {
[result addObject:@{ @"spacingAfter" : @(self.spacingAfter) }];
}
if (self.spacingBefore != defaultState.spacingBefore) {
if (self.spacingBefore != 0) {
[result addObject:@{ @"spacingBefore" : @(self.spacingBefore) }];
}
if (CGPointEqualToPoint(self.layoutPosition, defaultState.layoutPosition) == NO) {
if (CGPointEqualToPoint(self.layoutPosition, CGPointZero) == NO) {
[result addObject:@{ @"layoutPosition" : [NSValue valueWithCGPoint:self.layoutPosition] }];
}
@ -528,4 +592,3 @@ do {\
#pragma clang diagnostic pop
@end

View File

@ -10,7 +10,11 @@
// of patent rights can be found in the PATENTS file in the same directory.
//
#if AS_TARGET_OS_IOS
#import <UIKit/UIGeometry.h>
#else
#import <Foundation/NSGeometry.h>
#endif
@protocol ASLayoutElementExtensibility <NSObject>
@ -26,4 +30,5 @@
- (void)setLayoutOptionExtensionEdgeInsets:(UIEdgeInsets)value atIndex:(int)idx;
- (UIEdgeInsets)layoutOptionExtensionEdgeInsetsAtIndex:(int)idx;
@end

View File

@ -8,11 +8,20 @@
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <AsyncDisplayKit/ASAvailability.h>
#import <AsyncDisplayKit/ASDimension.h>
#if AS_TARGET_OS_IOS
#import <UIKit/UIGeometry.h>
#else
#import <Foundation/NSGeometry.h>
#endif
@protocol ASLayoutElement;
@class ASLayoutElementStyle;
#pragma mark - ASLayoutElementContext
struct ASLayoutElementContext {
int32_t transitionID;
BOOL needsVisualizeNode;
@ -34,11 +43,39 @@ extern struct ASLayoutElementContext ASLayoutElementGetCurrentContext();
extern void ASLayoutElementClearCurrentContext();
#pragma mark - ASLayoutElementLayoutDefaults
#define ASLayoutElementLayoutCalculationDefaults \
- (ASLayout *)layoutThatFits:(ASSizeRange)constrainedSize\
{\
_Pragma("clang diagnostic push")\
_Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")\
/* For now we just call the deprecated measureWithSizeRange: method to not break old API */ \
return [self measureWithSizeRange:constrainedSize]; \
_Pragma("clang diagnostic pop")\
} \
\
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize\
{\
return [self layoutThatFits:constrainedSize parentSize:constrainedSize.max];\
}\
\
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize\
restrictedToSize:(ASLayoutElementSize)size\
relativeToParentSize:(CGSize)parentSize\
{\
const ASSizeRange resolvedRange = ASSizeRangeIntersect(constrainedSize, ASLayoutElementSizeResolve(self.style.size, parentSize));\
return [self calculateLayoutThatFits:resolvedRange];\
}\
#pragma mark - ASLayoutElementFinalLayoutElement
/**
* The base protocol for ASLayoutElement. Generally the methods/properties in this class do not need to be
* The base protocol for ASLayoutElementFinalLayoutElement. Generally the methods/properties in this class do not need to be
* called by the end user and are only called internally. However, there may be a case where the methods are useful.
*/
@protocol ASLayoutElementPrivate <NSObject>
@protocol ASLayoutElementFinalLayoutElement <NSObject>
/**
* @abstract This method can be used to give the user a chance to wrap an ASLayoutElement in an ASLayoutSpec
@ -61,40 +98,65 @@ extern void ASLayoutElementClearCurrentContext();
@end
// Default implementation for ASLayoutElementPrivate that can be used in classes that comply to ASLayoutElementPrivate
#define ASLayoutElementFinalLayoutElementDefault \
\
@synthesize isFinalLayoutElement = _isFinalLayoutElement;\
\
- (id<ASLayoutElement>)finalLayoutElement\
{\
return self;\
}\
#pragma mark - ASLayoutElementExtensibility
#define ASEnvironmentLayoutExtensibilityForwarding \
// Provides extension points for elments that comply to ASLayoutElement like ASLayoutSpec to add additional
// properties besides the default one provided in ASLayoutElementStyle
static const int kMaxLayoutElementBoolExtensions = 1;
static const int kMaxLayoutElementStateIntegerExtensions = 4;
static const int kMaxLayoutElementStateEdgeInsetExtensions = 1;
typedef struct ASLayoutElementStyleExtensions {
// Values to store extensions
BOOL boolExtensions[kMaxLayoutElementBoolExtensions];
NSInteger integerExtensions[kMaxLayoutElementStateIntegerExtensions];
UIEdgeInsets edgeInsetsExtensions[kMaxLayoutElementStateEdgeInsetExtensions];
} ASLayoutElementStyleExtensions;
#define ASLayoutElementStyleExtensibilityForwarding \
- (void)setLayoutOptionExtensionBool:(BOOL)value atIndex:(int)idx\
{\
_ASEnvironmentLayoutOptionsExtensionSetBoolAtIndex(self, idx, value);\
[self.style setLayoutOptionExtensionBool:value atIndex:idx];\
}\
\
- (BOOL)layoutOptionExtensionBoolAtIndex:(int)idx\
{\
return _ASEnvironmentLayoutOptionsExtensionGetBoolAtIndex(self, idx);\
return [self.style layoutOptionExtensionBoolAtIndex:idx];\
}\
\
- (void)setLayoutOptionExtensionInteger:(NSInteger)value atIndex:(int)idx\
{\
_ASEnvironmentLayoutOptionsExtensionSetIntegerAtIndex(self, idx, value);\
[self.style setLayoutOptionExtensionInteger:value atIndex:idx];\
}\
\
- (NSInteger)layoutOptionExtensionIntegerAtIndex:(int)idx\
{\
return _ASEnvironmentLayoutOptionsExtensionGetIntegerAtIndex(self, idx);\
return [self.style layoutOptionExtensionIntegerAtIndex:idx];\
}\
\
- (void)setLayoutOptionExtensionEdgeInsets:(UIEdgeInsets)value atIndex:(int)idx\
{\
_ASEnvironmentLayoutOptionsExtensionSetEdgeInsetsAtIndex(self, idx, value);\
[self.style setLayoutOptionExtensionEdgeInsets:value atIndex:idx];\
}\
\
- (UIEdgeInsets)layoutOptionExtensionEdgeInsetsAtIndex:(int)idx\
{\
return _ASEnvironmentLayoutOptionsExtensionGetEdgeInsetsAtIndex(self, idx);\
return [self.style layoutOptionExtensionEdgeInsetsAtIndex:idx];\
}\
#pragma mark ASLayoutElementStyleForwardingDeclaration (Deprecated)
#define ASLayoutElementStyleForwardingDeclaration \

View File

@ -7,8 +7,7 @@
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <AsyncDisplayKit/ASLayoutSpec.h>
#import <AsyncdisplayKit/ASLayoutSpec.h>
#import <AsyncDisplayKit/ASLayout.h>
NS_ASSUME_NONNULL_BEGIN

View File

@ -54,14 +54,9 @@
if (self.isFinalLayoutElement == NO) {
id<ASLayoutElement> finalLayoutElement = [child finalLayoutElement];
if (finalLayoutElement != child) {
if (ASEnvironmentStatePropagationEnabled()) {
ASEnvironmentStatePropagateUp(finalLayoutElement, child.environmentState.layoutOptionsState);
} else {
// If state propagation is not enabled the layout options state needs to be copied manually
ASEnvironmentState finalLayoutElementEnvironmentState = finalLayoutElement.environmentState;
finalLayoutElementEnvironmentState.layoutOptionsState = child.environmentState.layoutOptionsState;
finalLayoutElement.environmentState = finalLayoutElementEnvironmentState;
}
#if AS_TARGET_OS_IOS
finalLayoutElement.primitiveTraitCollection = child.primitiveTraitCollection;
#endif
return finalLayoutElement;
}
}

View File

@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* A layout spec is an immutable object that describes a layout, loosely inspired by React.
*/
@interface ASLayoutSpec : NSObject <ASLayoutElement>
@interface ASLayoutSpec : NSObject <ASLayoutElement, ASLayoutElementStylability, NSFastEnumeration>
/**
* Creation of a layout spec should only happen by a user in layoutSpecThatFits:. During that method, a
@ -31,9 +31,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nullable, nonatomic, weak) id<ASLayoutElement> parent;
/**
* Adds a child to this layout spec using a default identifier.
*
* @param child A child to be added.
* First child within the children's array.
*
* @discussion Every ASLayoutSpec must act on at least one child. The ASLayoutSpec base class takes the
* responsibility of holding on to the spec children. Some layout specs, like ASInsetLayoutSpec,
@ -48,9 +46,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nullable, strong, nonatomic) id<ASLayoutElement> child;
/**
* Adds childen to this layout spec.
*
* @param children An array of ASLayoutElement children to be added.
* An array of ASLayoutElement children
*
* @discussion Every ASLayoutSpec must act on at least one child. The ASLayoutSpec base class takes the
* reponsibility of holding on to the spec children. Some layout specs, like ASStackLayoutSpec,

View File

@ -17,6 +17,8 @@
#import <AsyncDisplayKit/ASLayoutElementStylePrivate.h>
#import <AsyncDisplayKit/ASTraitCollection.h>
#import <AsyncDisplayKit/ASEqualityHelpers.h>
#import <AsyncDisplayKit/ASAvailability.h>
#import <AsyncDisplayKit/ASInternalHelpers.h>
#import <objc/runtime.h>
#import <map>
@ -27,7 +29,6 @@
// Dynamic properties for ASLayoutElements
@dynamic layoutElementType;
@synthesize debugName = _debugName;
@synthesize isFinalLayoutElement = _isFinalLayoutElement;
#pragma mark - Class
@ -49,7 +50,9 @@
}
_isMutable = YES;
_environmentState = ASEnvironmentStateMakeDefault();
#if AS_TARGET_OS_IOS
_primitiveTraitCollection = ASPrimitiveTraitCollectionMakeDefault();
#endif
_childrenArray = [[NSMutableArray alloc] init];
return self;
@ -67,23 +70,30 @@
#pragma mark - Final LayoutElement
@synthesize isFinalLayoutElement = _isFinalLayoutElement;
- (id<ASLayoutElement>)finalLayoutElement
{
#if ASLAYOUTSPEC_DEBUG
if (ASLayoutElementGetCurrentContext().needsVisualizeNode && !self.neverShouldVisualize) {
return [[ASLayoutSpecVisualizerNode alloc] initWithLayoutSpec:self];
} else {
return self;
}
#else
return self;
#endif
}
- (void)recursivelySetShouldVisualize:(BOOL)visualize
{
NSMutableArray *mutableChildren = [self.children mutableCopy];
#if ASLAYOUTSPEC_DEBUG
for (id<ASLayoutElement>layoutElement in self.children) {
if (layoutElement.layoutElementType == ASLayoutElementTypeLayoutSpec) {
ASLayoutSpec *layoutSpec = (ASLayoutSpec *)layoutElement;
[mutableChildren replaceObjectAtIndex:[mutableChildren indexOfObjectIdenticalTo:layoutSpec]
withObject:[[ASLayoutSpecVisualizerNode alloc] initWithLayoutSpec:layoutSpec]];
@ -91,6 +101,7 @@
layoutSpec.shouldVisualize = visualize;
}
}
#endif
if ([mutableChildren count] == 1) { // HACK for wrapper layoutSpecs (e.g. insetLayoutSpec)
self.child = mutableChildren[0];
@ -110,7 +121,7 @@
return _style;
}
- (instancetype)styledWithBlock:(void (^)(ASLayoutElementStyle *style))styleBlock
- (instancetype)styledWithBlock:(AS_NOESCAPE void (^)(__kindof ASLayoutElementStyle *style))styleBlock
{
styleBlock(self.style);
return self;
@ -190,7 +201,12 @@
}
}
- (NSArray *)children
- (nullable NSArray<id<ASLayoutElement>> *)children
{
return [_childrenArray copy];
}
- (NSArray<id<ASLayoutElement>> *)sublayoutElements
{
return [_childrenArray copy];
}
@ -202,40 +218,35 @@
return [_childrenArray countByEnumeratingWithState:state objects:buffer count:len];
}
#pragma mark - ASEnvironment
#pragma mark - ASTraitEnvironment
- (ASEnvironmentState)environmentState
#if AS_TARGET_OS_IOS
- (ASPrimitiveTraitCollection)primitiveTraitCollection
{
return _environmentState;
return _primitiveTraitCollection;
}
- (void)setEnvironmentState:(ASEnvironmentState)environmentState
- (void)setPrimitiveTraitCollection:(ASPrimitiveTraitCollection)traitCollection
{
_environmentState = environmentState;
}
- (BOOL)supportsTraitsCollectionPropagation
{
return ASEnvironmentStateTraitCollectionPropagationEnabled();
}
- (ASEnvironmentTraitCollection)environmentTraitCollection
{
return _environmentState.environmentTraitCollection;
}
- (void)setEnvironmentTraitCollection:(ASEnvironmentTraitCollection)environmentTraitCollection
{
_environmentState.environmentTraitCollection = environmentTraitCollection;
_primitiveTraitCollection = traitCollection;
}
- (ASTraitCollection *)asyncTraitCollection
{
ASDN::MutexLocker l(__instanceLock__);
return [ASTraitCollection traitCollectionWithASEnvironmentTraitCollection:self.environmentTraitCollection];
return [ASTraitCollection traitCollectionWithASPrimitiveTraitCollection:self.primitiveTraitCollection];
}
ASEnvironmentLayoutExtensibilityForwarding
#endif
#if AS_TARGET_OS_IOS
ASPrimitiveTraitCollectionDeprecatedImplementation
#endif
#pragma mark - ASLayoutElementStyleExtensibility
ASLayoutElementStyleExtensibilityForwarding
#pragma mark - Framework Private

View File

@ -98,11 +98,11 @@ typedef NS_ENUM(NSUInteger, ASHorizontalAlignment) {
// After 2.0 has landed, we'll add ASDISPLAYNODE_DEPRECATED here - for now, avoid triggering errors for projects with -Werror
/** @deprecated Use ASHorizontalAlignmentLeft instead */
ASAlignmentLeft = ASHorizontalAlignmentLeft,
ASAlignmentLeft ASDISPLAYNODE_DEPRECATED = ASHorizontalAlignmentLeft,
/** @deprecated Use ASHorizontalAlignmentMiddle instead */
ASAlignmentMiddle = ASHorizontalAlignmentMiddle,
ASAlignmentMiddle ASDISPLAYNODE_DEPRECATED = ASHorizontalAlignmentMiddle,
/** @deprecated Use ASHorizontalAlignmentRight instead */
ASAlignmentRight = ASHorizontalAlignmentRight,
ASAlignmentRight ASDISPLAYNODE_DEPRECATED = ASHorizontalAlignmentRight,
};
/** Orientation of children along vertical axis */
@ -118,9 +118,9 @@ typedef NS_ENUM(NSUInteger, ASVerticalAlignment) {
// After 2.0 has landed, we'll add ASDISPLAYNODE_DEPRECATED here - for now, avoid triggering errors for projects with -Werror
/** @deprecated Use ASVerticalAlignmentTop instead */
ASAlignmentTop = ASVerticalAlignmentTop,
ASAlignmentTop ASDISPLAYNODE_DEPRECATED = ASVerticalAlignmentTop,
/** @deprecated Use ASVerticalAlignmentCenter instead */
ASAlignmentCenter = ASVerticalAlignmentCenter,
ASAlignmentCenter ASDISPLAYNODE_DEPRECATED = ASVerticalAlignmentCenter,
/** @deprecated Use ASVerticalAlignmentBottom instead */
ASAlignmentBottom = ASVerticalAlignmentBottom,
ASAlignmentBottom ASDISPLAYNODE_DEPRECATED = ASVerticalAlignmentBottom,
};

View File

@ -21,9 +21,6 @@
#import <AsyncDisplayKit/ASStackPositionedLayout.h>
#import <AsyncDisplayKit/ASStackUnpositionedLayout.h>
#import <AsyncDisplayKit/ASInternalHelpers.h>
#import <AsyncDisplayKit/ASThread.h>
@implementation ASStackLayoutSpec
- (instancetype)init

View File

@ -19,7 +19,6 @@
#import <AsyncDisplayKit/_ASTransitionContext.h>
#import <AsyncDisplayKit/ASLayoutElement.h>
#import <AsyncDisplayKit/ASLayoutTransition.h>
#import <AsyncDisplayKit/ASEnvironment.h>
#import <AsyncDisplayKit/ASWeakSet.h>
#import <AsyncDisplayKit/ASDisplayNode+Beta.h>
@ -111,14 +110,13 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
NSMutableArray *_subnodes;
ASLayoutElementStyle *_style;
ASPrimitiveTraitCollection _primitiveTraitCollection;
std::atomic_uint _displaySentinel;
// This is the desired contentsScale, not the scale at which the layer's contents should be displayed
CGFloat _contentsScaleForDisplay;
ASEnvironmentState _environmentState;
UIEdgeInsets _hitTestSlop;
#if ASEVENTLOG_ENABLE
@ -280,7 +278,7 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
* Convenience method to access this node's trait collection struct. Externally, users should interact
* with the trait collection via ASTraitCollection
*/
- (ASEnvironmentTraitCollection)environmentTraitCollection;
- (ASPrimitiveTraitCollection)primitiveTraitCollection;
@end

View File

@ -1,79 +0,0 @@
//
// ASEnvironmentInternal.h
// AsyncDisplayKit
//
// 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/ASEnvironment.h>
#pragma once
BOOL ASEnvironmentStatePropagationEnabled();
BOOL ASEnvironmentStateTraitCollectionPropagationEnabled();
#pragma mark - Set and get extensible values for layout options
void _ASEnvironmentLayoutOptionsExtensionSetBoolAtIndex(id<ASEnvironment> object, int idx, BOOL value);
BOOL _ASEnvironmentLayoutOptionsExtensionGetBoolAtIndex(id<ASEnvironment> object, int idx);
void _ASEnvironmentLayoutOptionsExtensionSetIntegerAtIndex(id<ASEnvironment> object, int idx, NSInteger value);
NSInteger _ASEnvironmentLayoutOptionsExtensionGetIntegerAtIndex(id<ASEnvironment> object, int idx);
void _ASEnvironmentLayoutOptionsExtensionSetEdgeInsetsAtIndex(id<ASEnvironment> object, int idx, UIEdgeInsets value);
UIEdgeInsets _ASEnvironmentLayoutOptionsExtensionGetEdgeInsetsAtIndex(id<ASEnvironment> object, int idx);
#pragma mark - Traversing an ASEnvironment Tree
void ASEnvironmentPerformBlockOnObjectAndChildren(id<ASEnvironment> object, void(^block)(id<ASEnvironment> object));
void ASEnvironmentPerformBlockOnObjectAndParents(id<ASEnvironment> object, void(^block)(id<ASEnvironment> object));
#pragma mark -
enum class ASEnvironmentStatePropagation { DOWN, UP };
#pragma mark - Merging
static const struct ASEnvironmentStateExtensions ASEnvironmentDefaultStateExtensions = {};
static const struct ASEnvironmentLayoutOptionsState ASEnvironmentDefaultLayoutOptionsState = ASEnvironmentLayoutOptionsStateMakeDefault();
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentLayoutOptionsState state, ASEnvironmentStatePropagation propagation);
static const struct ASEnvironmentHierarchyState ASEnvironmentDefaultHierarchyState = ASEnvironmentHierarchyStateMakeDefault();
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentHierarchyState state, ASEnvironmentStatePropagation propagation);
static const struct ASEnvironmentTraitCollection ASEnvironmentDefaultTraitCollection = ASEnvironmentTraitCollectionMakeDefault();
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentTraitCollection state, ASEnvironmentStatePropagation propagation);
#pragma mark - Propagation
template <typename ASEnvironmentStateType>
void ASEnvironmentStatePropagateDown(id<ASEnvironment> object, ASEnvironmentStateType state) {
ASEnvironmentPerformBlockOnObjectAndChildren(object, ^(id<ASEnvironment> node) {
node.environmentState = ASEnvironmentMergeObjectAndState(node.environmentState, state, ASEnvironmentStatePropagation::DOWN);
});
}
template <typename ASEnvironmentStateType>
void ASEnvironmentStatePropagateUp(id<ASEnvironment> object, ASEnvironmentStateType state) {
ASEnvironmentPerformBlockOnObjectAndParents(object, ^(id<ASEnvironment> node) {
node.environmentState = ASEnvironmentMergeObjectAndState(node.environmentState, state, ASEnvironmentStatePropagation::UP);
});
}
template <typename ASEnvironmentStateType>
void ASEnvironmentStateApply(id<ASEnvironment> object, ASEnvironmentStateType& state, ASEnvironmentStatePropagation propagate) {
if (propagate == ASEnvironmentStatePropagation::DOWN) {
ASEnvironmentStatePropagateUp(object, state);
} else if (propagate == ASEnvironmentStatePropagation::UP) {
ASEnvironmentStatePropagateDown(object, state);
}
}

View File

@ -1,217 +0,0 @@
//
// ASEnvironmentInternal.mm
// AsyncDisplayKit
//
// 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/ASEnvironmentInternal.h>
#import <queue>
//#define LOG(...) NSLog(__VA_ARGS__)
#define LOG(...)
#define AS_SUPPORT_PROPAGATION YES
#define AS_DOES_NOT_SUPPORT_PROPAGATION NO
BOOL ASEnvironmentStatePropagationEnabled()
{
return AS_DOES_NOT_SUPPORT_PROPAGATION;
}
BOOL ASEnvironmentStateTraitCollectionPropagationEnabled()
{
return AS_SUPPORT_PROPAGATION;
}
#pragma mark - Traversing an ASEnvironment Tree
void ASEnvironmentPerformBlockOnObjectAndChildren(id<ASEnvironment> object, void(^block)(id<ASEnvironment> node))
{
if (!object) {
return;
}
std::queue<id<ASEnvironment>> queue;
queue.push(object);
while (!queue.empty()) {
id<ASEnvironment> object = queue.front(); queue.pop();
block(object);
for (id<ASEnvironment> child in [object children]) {
queue.push(child);
}
}
}
void ASEnvironmentPerformBlockOnObjectAndParents(id<ASEnvironment> object, void(^block)(id<ASEnvironment> node))
{
while (object) {
block(object);
object = [object parent];
}
}
#pragma mark - Set and get extensible values from state structs
void _ASEnvironmentLayoutOptionsExtensionSetBoolAtIndex(id<ASEnvironment> object, int idx, BOOL value)
{
NSCAssert(idx < kMaxEnvironmentStateBoolExtensions, @"Setting index outside of max bool extensions space");
ASEnvironmentState state = object.environmentState;
state.layoutOptionsState._extensions.boolExtensions[idx] = value;
object.environmentState = state;
}
BOOL _ASEnvironmentLayoutOptionsExtensionGetBoolAtIndex(id<ASEnvironment> object, int idx)
{
NSCAssert(idx < kMaxEnvironmentStateBoolExtensions, @"Accessing index outside of max bool extensions space");
return object.environmentState.layoutOptionsState._extensions.boolExtensions[idx];
}
void _ASEnvironmentLayoutOptionsExtensionSetIntegerAtIndex(id<ASEnvironment> object, int idx, NSInteger value)
{
NSCAssert(idx < kMaxEnvironmentStateIntegerExtensions, @"Setting index outside of max integer extensions space");
ASEnvironmentState state = object.environmentState;
state.layoutOptionsState._extensions.integerExtensions[idx] = value;
object.environmentState = state;
}
NSInteger _ASEnvironmentLayoutOptionsExtensionGetIntegerAtIndex(id<ASEnvironment> object, int idx)
{
NSCAssert(idx < kMaxEnvironmentStateIntegerExtensions, @"Accessing index outside of max integer extensions space");
return object.environmentState.layoutOptionsState._extensions.integerExtensions[idx];
}
void _ASEnvironmentLayoutOptionsExtensionSetEdgeInsetsAtIndex(id<ASEnvironment> object, int idx, UIEdgeInsets value)
{
NSCAssert(idx < kMaxEnvironmentStateEdgeInsetExtensions, @"Setting index outside of max edge insets extensions space");
ASEnvironmentState state = object.environmentState;
state.layoutOptionsState._extensions.edgeInsetsExtensions[idx] = value;
object.environmentState = state;
}
UIEdgeInsets _ASEnvironmentLayoutOptionsExtensionGetEdgeInsetsAtIndex(id<ASEnvironment> object, int idx)
{
NSCAssert(idx < kMaxEnvironmentStateEdgeInsetExtensions, @"Accessing index outside of max edge insets extensions space");
return object.environmentState.layoutOptionsState._extensions.edgeInsetsExtensions[idx];
}
#pragma mark - Merging functions for states
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentHierarchyState hierarchyState, ASEnvironmentStatePropagation propagation) {
// Merge object and hierarchy state
LOG(@"Merge object and state: %@ - ASEnvironmentHierarchyState", hierarchyState);
return environmentState;
}
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environmentState, ASEnvironmentLayoutOptionsState layoutOptionsState, ASEnvironmentStatePropagation propagation) {
// Merge object and layout options state
LOG(@"Merge object and state: %@ - ASEnvironmentLayoutOptionsState", layoutOptionsState);
if (!ASEnvironmentStatePropagationEnabled() && propagation == ASEnvironmentStatePropagation::UP) {
return environmentState;
}
// Support propagate up
if (propagation == ASEnvironmentStatePropagation::UP) {
// Object is the parent and the state is the state of the child
const ASEnvironmentLayoutOptionsState defaultState = ASEnvironmentLayoutOptionsStateMakeDefault();
ASEnvironmentLayoutOptionsState parentLayoutOptionsState = environmentState.layoutOptionsState;
// For every field check if the parent value is equal to the default and if so propegate up the value of the passed
// in layout options state
if (parentLayoutOptionsState.spacingBefore == defaultState.spacingBefore) {
parentLayoutOptionsState.spacingBefore = layoutOptionsState.spacingBefore;
}
if (parentLayoutOptionsState.spacingAfter == defaultState.spacingAfter) {
parentLayoutOptionsState.spacingAfter = layoutOptionsState.spacingAfter;
}
if (parentLayoutOptionsState.alignSelf == defaultState.alignSelf) {
parentLayoutOptionsState.alignSelf = layoutOptionsState.alignSelf;
}
if (parentLayoutOptionsState.flexGrow == defaultState.flexGrow) {
parentLayoutOptionsState.flexGrow = layoutOptionsState.flexGrow;
}
if (parentLayoutOptionsState.flexShrink == defaultState.flexShrink) {
parentLayoutOptionsState.flexShrink = layoutOptionsState.flexShrink;
}
if (ASDimensionEqualToDimension(parentLayoutOptionsState.flexBasis, defaultState.flexBasis)) {
parentLayoutOptionsState.flexBasis = layoutOptionsState.flexBasis;
}
if (parentLayoutOptionsState.alignSelf == defaultState.alignSelf) {
parentLayoutOptionsState.alignSelf = layoutOptionsState.alignSelf;
}
if (parentLayoutOptionsState.ascender == defaultState.ascender) {
parentLayoutOptionsState.ascender = layoutOptionsState.ascender;
}
if (parentLayoutOptionsState.descender == defaultState.descender) {
parentLayoutOptionsState.descender = layoutOptionsState.descender;
}
if (CGPointEqualToPoint(parentLayoutOptionsState.layoutPosition, defaultState.layoutPosition)) {
// For now it is unclear if we should be up-propagating sizeRange or layoutPosition.
// parentLayoutOptionsState.layoutPosition = layoutOptionsState.layoutPosition;
}
// Merge extended values if necessary
const ASEnvironmentStateExtensions defaultExtensions = ASEnvironmentDefaultStateExtensions;
const ASEnvironmentStateExtensions layoutOptionsStateExtensions = layoutOptionsState._extensions;
ASEnvironmentStateExtensions parentLayoutOptionsExtensions = parentLayoutOptionsState._extensions;
for (int i = 0; i < kMaxEnvironmentStateBoolExtensions; i++) {
if (parentLayoutOptionsExtensions.boolExtensions[i] == defaultExtensions.boolExtensions[i]) {
parentLayoutOptionsExtensions.boolExtensions[i] = layoutOptionsStateExtensions.boolExtensions[i];
}
}
for (int i = 0; i < kMaxEnvironmentStateIntegerExtensions; i++) {
if (parentLayoutOptionsExtensions.integerExtensions[i] == defaultExtensions.integerExtensions[i]) {
parentLayoutOptionsExtensions.integerExtensions[i] = layoutOptionsStateExtensions.integerExtensions[i];
}
}
for (int i = 0; i < kMaxEnvironmentStateEdgeInsetExtensions; i++) {
if (UIEdgeInsetsEqualToEdgeInsets(parentLayoutOptionsExtensions.edgeInsetsExtensions[i], defaultExtensions.edgeInsetsExtensions[i])) {
parentLayoutOptionsExtensions.edgeInsetsExtensions[i] = layoutOptionsStateExtensions.edgeInsetsExtensions[i];
}
}
parentLayoutOptionsState._extensions = parentLayoutOptionsExtensions;
// Update layout options state
environmentState.layoutOptionsState = parentLayoutOptionsState;
}
return environmentState;
}
ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState childEnvironmentState, ASEnvironmentTraitCollection parentTraitCollection, ASEnvironmentStatePropagation propagation) {
if (propagation == ASEnvironmentStatePropagation::DOWN && !ASEnvironmentStateTraitCollectionPropagationEnabled()) {
return childEnvironmentState;
}
// Support propagate down
if (propagation == ASEnvironmentStatePropagation::DOWN) {
ASEnvironmentTraitCollection childTraitCollection = childEnvironmentState.environmentTraitCollection;
childTraitCollection.horizontalSizeClass = parentTraitCollection.horizontalSizeClass;
childTraitCollection.verticalSizeClass = parentTraitCollection.verticalSizeClass;
childTraitCollection.userInterfaceIdiom = parentTraitCollection.userInterfaceIdiom;
childTraitCollection.forceTouchCapability = parentTraitCollection.forceTouchCapability;
childTraitCollection.displayScale = parentTraitCollection.displayScale;
childTraitCollection.containerSize = parentTraitCollection.containerSize;
childEnvironmentState.environmentTraitCollection = childTraitCollection;
}
return childEnvironmentState;
}

View File

@ -8,7 +8,13 @@
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "ASAvailability.h"
#if AS_TARGET_OS_IOS
#import <UIKit/UIKit.h>
#else
#import <QuartzCore/QuartzCore.h>
#endif
#import <AsyncDisplayKit/ASBaseDefines.h>
@ -71,7 +77,14 @@ ASDISPLAYNODE_INLINE BOOL ASImageAlphaInfoIsOpaque(CGImageAlphaInfo info) {
*/
ASDISPLAYNODE_INLINE void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) {
if (withoutAnimation) {
#if AS_TARGET_OS_IOS
[UIView performWithoutAnimation:block];
#else
[CATransaction begin];
[CATransaction setDisableActions: YES];
block();
[CATransaction commit];
#endif
} else {
block();
}

View File

@ -10,6 +10,12 @@
#import <AsyncDisplayKit/ASInternalHelpers.h>
#if AS_TARGET_OS_IOS
#import <UIKit/UIKit.h>
#else
#import <AppKit/AppKit.h>
#endif
#import <objc/runtime.h>
#import <tgmath.h>
@ -86,15 +92,29 @@ void ASPerformBackgroundDeallocation(id object)
BOOL ASClassRequiresMainThreadDeallocation(Class c)
{
#if AS_TARGET_OS_IOS
if (c == [UIImage class] || c == [UIColor class]) {
return NO;
}
if ([c isSubclassOfClass:[UIResponder class]]
|| [c isSubclassOfClass:[CALayer class]]
|| [c isSubclassOfClass:[UIGestureRecognizer class]]) {
return YES;
}
#else
if (c == [NSImage class] || c == [NSColor class]) {
return NO;
}
if ([c isSubclassOfClass:[NSResponder class]]
|| [c isSubclassOfClass:[CALayer class]]
|| [c isSubclassOfClass:[NSGestureRecognizer class]]) {
return YES;
}
#endif
const char *name = class_getName(c);
if (strncmp(name, "UI", 2) == 0 || strncmp(name, "AV", 2) == 0 || strncmp(name, "CA", 2) == 0) {
@ -132,7 +152,11 @@ CGFloat ASScreenScale()
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
ASDisplayNodeCAssertMainThread();
#if AS_TARGET_OS_IOS
__scale = [[UIScreen mainScreen] scale];
#else
__scale = [[NSScreen mainScreen] backingScaleFactor];
#endif
});
return __scale;
}

View File

@ -15,11 +15,34 @@
#import <AsyncDisplayKit/ASDisplayNodeLayout.h>
#import <AsyncDisplayKit/ASBaseDefines.h>
#import <AsyncDisplayKit/ASDisplayNode.h>
#import <AsyncDisplayKit/ASLayoutSpec.h>
#import <memory>
NS_ASSUME_NONNULL_BEGIN
@class ASDisplayNode;
#pragma mark - ASLayoutElementTransition
/**
* Extend the layout element protocol to check if a the element can layout asynchronously.
*/
@protocol ASLayoutElementTransition <ASLayoutElement>
/**
* @abstract Returns if the layoutElement can be used to layout in an asynchronous way on a background thread.
*/
@property (nonatomic, assign, readonly) BOOL canLayoutAsynchronous;
@end
@interface ASDisplayNode () <ASLayoutElementTransition>
@end
@interface ASLayoutSpec () <ASLayoutElementTransition>
@end
#pragma mark - ASLayoutTransition
AS_SUBCLASSING_RESTRICTED
@interface ASLayoutTransition : NSObject <_ASTransitionContextLayoutDelegate>

View File

@ -37,7 +37,10 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) {
layout = queue.front();
queue.pop();
if (layout.layoutElement.canLayoutAsynchronous == NO) {
#if DEBUG
ASDisplayNodeCAssert([layout.layoutElement conformsToProtocol:@protocol(ASLayoutElementTransition)], @"ASLayoutElement in a layout transition needs to conforms to the ASLayoutElementTransition protocol.");
#endif
if (((id<ASLayoutElementTransition>)layout.layoutElement).canLayoutAsynchronous == NO) {
return NO;
}

View File

@ -10,17 +10,17 @@
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <AsyncDisplayKit/ASAvailability.h>
#import <AsyncDisplayKit/ASInternalHelpers.h>
#import <AsyncDisplayKit/ASThread.h>
#import <AsyncDisplayKit/ASEnvironmentInternal.h>
NS_ASSUME_NONNULL_BEGIN
@interface ASLayoutSpec() {
ASDN::RecursiveMutex __instanceLock__;
ASEnvironmentState _environmentState;
#if AS_TARGET_OS_IOS
ASPrimitiveTraitCollection _primitiveTraitCollection;
#endif
ASLayoutElementStyle *_style;
NSMutableArray *_childrenArray;
}

View File

@ -8,7 +8,7 @@
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>
#import <algorithm>
#import <functional>
@ -102,4 +102,3 @@ inline UIEdgeInsets operator-(const UIEdgeInsets &e)
{
return { -e.top, -e.left, -e.bottom, -e.right };
}

View File

@ -97,7 +97,7 @@ static const CGFloat kViolationEpsilon = 0.01;
|
+--------------------------------------------------+ + crossMax
@param layouts pre-computed child layouts; modified in-place as needed
@param items pre-computed child layouts; modified in-place as needed
@param style the layout style of the overall stack layout
*/
static void stretchChildrenAlongCrossDimension(std::vector<ASStackLayoutSpecItem> &items,
@ -147,7 +147,7 @@ CGFloat ASStackUnpositionedLayout::baselineForItem(const ASStackLayoutSpecStyle
* Finds cross dimension size and baseline of the stack.
* https://www.w3.org/TR/css-flexbox-1/#algo-cross-line
*
* @param layout the unpositioned layout
* @param items All items to lay out
* @param style the layout style of the overall stack layout
* @param sizeRange the range of allowable sizes for the stack layout component
* @param crossSize result of the cross size
@ -403,7 +403,7 @@ ASDISPLAYNODE_INLINE BOOL useOptimizedFlexing(const std::vector<ASStackLayoutSpe
@param items Reference to unpositioned items from the original, unconstrained layout pass; modified in-place
@param style layout style to be applied to all children
@param sizeRange the range of allowable sizes for the stack layout component
@param size Size of the stack layout component. May be undefined in either or both directions.
@param parentSize Size of the stack layout component. May be undefined in either or both directions.
*/
static void flexChildrenAlongStackDimension(std::vector<ASStackLayoutSpecItem> &items,
const ASStackLayoutSpecStyle &style,

View File

@ -20,3 +20,50 @@
#define AS_AT_LEAST_IOS9 (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_9_0)
#define AS_AT_LEAST_IOS10 (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_10_0)
#define AS_TARGET_OS_OSX (!(TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH))
#define AS_TARGET_OS_IOS TARGET_OS_IPHONE
#if AS_TARGET_OS_OSX
#define UIEdgeInsets NSEdgeInsets
#define NSStringFromCGSize NSStringFromSize
#define NSStringFromCGPoint NSStringFromPoint
#import <Foundation/Foundation.h>
@interface NSValue (ASAvailability)
+ (NSValue *)valueWithCGPoint:(CGPoint)point;
+ (NSValue *)valueWithCGSize:(CGSize)size;
- (CGRect)CGRectValue;
- (CGPoint)CGPointValue;
- (CGSize)CGSizeValue;
@end
@implementation NSValue(ASAvailability)
+ (NSValue *)valueWithCGPoint:(CGPoint)point
{
return [self valueWithPoint:point];
}
+ (NSValue *)valueWithCGSize:(CGSize)size
{
return [self valueWithSize:size];
}
- (CGRect)CGRectValue
{
return self.rectValue;
}
- (CGPoint)CGPointValue
{
return self.pointValue;
}
- (CGSize)CGSizeValue
{
return self.sizeValue;
}
@end
#endif

View File

@ -380,7 +380,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
F012A6F39E0149F18F564F50 /* [CP] Copy Pods Resources */ = {