[Layout] Add delegate to ASLayoutableStyle for property changes (#2283)

* Add delegate to ASLayoutableStyle for property changes

* Moving ASLayoutableStyle delegate to readonly

* Add ASLayoutableStyleTests

* Fix property stirngs

* Fix video example

* Address comments of Adlai
This commit is contained in:
Michael Schneider
2016-09-27 13:50:36 -07:00
committed by Adlai Holler
parent f574f2c54e
commit 416d8f92e1
6 changed files with 238 additions and 13 deletions

View File

@@ -221,6 +221,7 @@
69E1006F1CA89CB600D88C1B /* ASEnvironmentInternal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */; };
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 /* ASLayoutableStyleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 69FEE53C1D95A9AF0086F066 /* ASLayoutableStyleTests.m */; };
7630FFA81C9E267E007A7C0E /* ASVideoNode.h in Headers */ = {isa = PBXBuildFile; fileRef = AEEC47DF1C20C2DD00EC1693 /* ASVideoNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
764D83D51C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h in Headers */ = {isa = PBXBuildFile; fileRef = 764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */; settings = {ATTRIBUTES = (Public, ); }; };
764D83D61C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m in Sources */ = {isa = PBXBuildFile; fileRef = 764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */; };
@@ -996,6 +997,7 @@
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 /* ASLayoutableStyleTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASLayoutableStyleTests.m; sourceTree = "<group>"; };
6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; path = AsyncDisplayKit.h; sourceTree = "<group>"; };
764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "AsyncDisplayKit+Debug.h"; sourceTree = "<group>"; };
764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "AsyncDisplayKit+Debug.m"; sourceTree = "<group>"; };
@@ -1419,6 +1421,7 @@
058D09C6195D04C000B7D73C /* Supporting Files */,
052EE06A1A15A0D8002C6279 /* TestResources */,
2538B6F21BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m */,
69FEE53C1D95A9AF0086F066 /* ASLayoutableStyleTests.m */,
);
path = AsyncDisplayKitTests;
sourceTree = "<group>";
@@ -2251,6 +2254,7 @@
CCB2F34D1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m in Sources */,
058D0A3A195D057000B7D73C /* ASDisplayNodeTests.m in Sources */,
696FCB311D6E46050093471E /* ASBackgroundLayoutSpecSnapshotTests.mm in Sources */,
69FEE53D1D95A9AF0086F066 /* ASLayoutableStyleTests.m in Sources */,
CC4981B31D1A02BE004E13CC /* ASTableViewThrashTests.m in Sources */,
CC54A81E1D7008B300296A24 /* ASDispatchTests.m in Sources */,
058D0A3B195D057000B7D73C /* ASDisplayNodeTestsHelper.m in Sources */,

View File

@@ -705,7 +705,7 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
ASDisplayNodeAssert(NO, @"Infinite width or height in ASVideoPlayerNode");
maxSize = CGSizeZero;
}
_videoNode.style.size = ASLayoutableSizeMakeFromCGSize(maxSize);
[_videoNode.style setSizeWithCGSize:maxSize];
ASLayoutSpec *layoutSpec;
if (_delegateFlags.delegateLayoutSpecForControls) {
@@ -718,12 +718,12 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
if (_spinnerNode) {
ASCenterLayoutSpec *centerLayoutSpec = [ASCenterLayoutSpec centerLayoutSpecWithCenteringOptions:ASCenterLayoutSpecCenteringXY sizingOptions:ASCenterLayoutSpecSizingOptionDefault child:_spinnerNode];
centerLayoutSpec.style.size = ASLayoutableSizeMakeFromCGSize(maxSize);
[centerLayoutSpec.style setSizeWithCGSize:maxSize];
[children addObject:centerLayoutSpec];
}
ASOverlayLayoutSpec *overlaySpec = [ASOverlayLayoutSpec overlayLayoutSpecWithChild:_videoNode overlay:layoutSpec];
overlaySpec.style.size = ASLayoutableSizeMakeFromCGSize(maxSize);
[overlaySpec.style setSizeWithCGSize:maxSize];
[children addObject:overlaySpec];
return [ASStaticLayoutSpec staticLayoutSpecWithChildren:children];

View File

@@ -150,18 +150,52 @@ NS_ASSUME_NONNULL_BEGIN
@end
#pragma mark - ASLayoutableStyle
extern NSString * const ASLayoutableStyleWidthProperty;
extern NSString * const ASLayoutableStyleMinWidthProperty;
extern NSString * const ASLayoutableStyleMaxWidthProperty;
extern NSString * const ASLayoutableStyleHeightProperty;
extern NSString * const ASLayoutableStyleMinHeightProperty;
extern NSString * const ASLayoutableStyleMaxHeightProperty;
extern NSString * const ASLayoutableStyleSpacingBeforeProperty;
extern NSString * const ASLayoutableStyleSpacingAfterProperty;
extern NSString * const ASLayoutableStyleFlexGrowProperty;
extern NSString * const ASLayoutableStyleFlexShrinkProperty;
extern NSString * const ASLayoutableStyleFlexBasisProperty;
extern NSString * const ASLayoutableStyleAlignSelfProperty;
extern NSString * const ASLayoutableStyleAscenderProperty;
extern NSString * const ASLayoutableStyleDescenderProperty;
extern NSString * const ASLayoutableStyleLayoutPositionProperty;
@protocol ASLayoutableStyleDelegate <NSObject>
- (void)style:(__kindof ASLayoutableStyle *)style propertyDidChange:(NSString *)propertyName;
@end
@interface ASLayoutableStyle : NSObject <ASStackLayoutable, ASStaticLayoutable>
#pragma mark - Delegate
#pragma mark - Sizing
/**
* @abstract Initializes the layoutable style with a specified delegate
*/
- (instancetype)initWithDelegate:(id<ASLayoutableStyleDelegate>)delegate;
/**
* @abstract The object that acts as the delegate of the style.
*
* @discussion The delegate must adopt the ASLayoutableStyleDelegate protocol. The delegate is not retained.
*/
@property (nullable, nonatomic, weak, readonly) id<ASLayoutableStyleDelegate> delegate;
// TODO: Move to internal method?
/**
* @abstract A size constraint that should apply to this ASLayoutable.
*/
@property (nonatomic, assign, readwrite) ASLayoutableSize size;
@property (nonatomic, assign, readonly) ASLayoutableSize size;
/**
* @abstract The width property specifies the height of the content area of an ASLayoutable.

View File

@@ -86,12 +86,52 @@ void ASLayoutableClearCurrentContext()
#pragma mark - ASLayoutableStyle
NSString * const ASLayoutableStyleWidthProperty = @"ASLayoutableStyleWidthProperty";
NSString * const ASLayoutableStyleMinWidthProperty = @"ASLayoutableStyleMinWidthProperty";
NSString * const ASLayoutableStyleMaxWidthProperty = @"ASLayoutableStyleMaxWidthProperty";
NSString * const ASLayoutableStyleHeightProperty = @"ASLayoutableStyleHeightProperty";
NSString * const ASLayoutableStyleMinHeightProperty = @"ASLayoutableStyleMinHeightProperty";
NSString * const ASLayoutableStyleMaxHeightProperty = @"ASLayoutableStyleMaxHeightProperty";
NSString * const ASLayoutableStyleSpacingBeforeProperty = @"ASLayoutableStyleSpacingBeforeProperty";
NSString * const ASLayoutableStyleSpacingAfterProperty = @"ASLayoutableStyleSpacingAfterProperty";
NSString * const ASLayoutableStyleFlexGrowProperty = @"ASLayoutableStyleFlexGrowProperty";
NSString * const ASLayoutableStyleFlexShrinkProperty = @"ASLayoutableStyleFlexShrinkProperty";
NSString * const ASLayoutableStyleFlexBasisProperty = @"ASLayoutableStyleFlexBasisProperty";
NSString * const ASLayoutableStyleAlignSelfProperty = @"ASLayoutableStyleAlignSelfProperty";
NSString * const ASLayoutableStyleAscenderProperty = @"ASLayoutableStyleAscenderProperty";
NSString * const ASLayoutableStyleDescenderProperty = @"ASLayoutableStyleDescenderProperty";
NSString * const ASLayoutableStyleLayoutPositionProperty = @"ASLayoutableStyleLayoutPositionProperty";
#define ASLayoutableStyleCallDelegate(propertyName)\
do {\
[_delegate style:self propertyDidChange:propertyName];\
} while(0)
@interface ASLayoutableStyle ()
@property (nullable, nonatomic, weak) id<ASLayoutableStyleDelegate> delegate;
@end
@implementation ASLayoutableStyle {
ASDN::RecursiveMutex __instanceLock__;
ASLayoutableSize _size;
}
@dynamic width, height, minWidth, maxWidth, minHeight, maxHeight;
#pragma mark - Lifecycle
- (instancetype)initWithDelegate:(id<ASLayoutableStyleDelegate>)delegate
{
self = [self init];
if (self) {
_delegate = delegate;
}
return self;
}
- (instancetype)init
{
self = [super init];
@@ -101,7 +141,6 @@ void ASLayoutableClearCurrentContext()
return self;
}
#pragma mark - ASLayoutableSizeForwarding
- (ASDimension)width
@@ -114,6 +153,7 @@ void ASLayoutableClearCurrentContext()
{
ASDN::MutexLocker l(__instanceLock__);
_size.width = width;
ASLayoutableStyleCallDelegate(ASLayoutableStyleWidthProperty);
}
- (ASDimension)height
@@ -126,6 +166,7 @@ void ASLayoutableClearCurrentContext()
{
ASDN::MutexLocker l(__instanceLock__);
_size.height = height;
ASLayoutableStyleCallDelegate(ASLayoutableStyleHeightProperty);
}
- (ASDimension)minWidth
@@ -138,6 +179,7 @@ void ASLayoutableClearCurrentContext()
{
ASDN::MutexLocker l(__instanceLock__);
_size.minWidth = minWidth;
ASLayoutableStyleCallDelegate(ASLayoutableStyleMinWidthProperty);
}
- (ASDimension)maxWidth
@@ -150,6 +192,7 @@ void ASLayoutableClearCurrentContext()
{
ASDN::MutexLocker l(__instanceLock__);
_size.maxWidth = maxWidth;
ASLayoutableStyleCallDelegate(ASLayoutableStyleMaxWidthProperty);
}
- (ASDimension)minHeight
@@ -162,6 +205,7 @@ void ASLayoutableClearCurrentContext()
{
ASDN::MutexLocker l(__instanceLock__);
_size.minHeight = minHeight;
ASLayoutableStyleCallDelegate(ASLayoutableStyleMinHeightProperty);
}
- (ASDimension)maxHeight
@@ -174,10 +218,9 @@ void ASLayoutableClearCurrentContext()
{
ASDN::MutexLocker l(__instanceLock__);
_size.maxHeight = maxHeight;
ASLayoutableStyleCallDelegate(ASLayoutableStyleMaxHeightProperty);
}
#pragma mark - Layout measurement and sizing
- (void)setSizeWithCGSize:(CGSize)size
{
self.width = ASDimensionMakeWithPoints(size.width);
@@ -192,4 +235,71 @@ void ASLayoutableClearCurrentContext()
self.maxHeight = ASDimensionMakeWithPoints(size.height);
}
#pragma mark - ASStackLayoutable
- (void)setSpacingBefore:(CGFloat)spacingBefore
{
ASDN::MutexLocker l(__instanceLock__);
_spacingBefore = spacingBefore;
ASLayoutableStyleCallDelegate(ASLayoutableStyleSpacingBeforeProperty);
}
- (void)setSpacingAfter:(CGFloat)spacingAfter
{
ASDN::MutexLocker l(__instanceLock__);
_spacingAfter = spacingAfter;
ASLayoutableStyleCallDelegate(ASLayoutableStyleSpacingAfterProperty);
}
- (void)setFlexGrow:(BOOL)flexGrow
{
ASDN::MutexLocker l(__instanceLock__);
_flexGrow = flexGrow;
ASLayoutableStyleCallDelegate(ASLayoutableStyleFlexGrowProperty);
}
- (void)setFlexShrink:(BOOL)flexShrink
{
ASDN::MutexLocker l(__instanceLock__);
_flexShrink = flexShrink;
ASLayoutableStyleCallDelegate(ASLayoutableStyleFlexShrinkProperty);
}
- (void)setFlexBasis:(ASDimension)flexBasis
{
ASDN::MutexLocker l(__instanceLock__);
_flexBasis = flexBasis;
ASLayoutableStyleCallDelegate(ASLayoutableStyleFlexBasisProperty);
}
- (void)setAlignSelf:(ASStackLayoutAlignSelf)alignSelf
{
ASDN::MutexLocker l(__instanceLock__);
_alignSelf = alignSelf;
ASLayoutableStyleCallDelegate(ASLayoutableStyleAlignSelfProperty);
}
- (void)setAscender:(CGFloat)ascender
{
ASDN::MutexLocker l(__instanceLock__);
_ascender = ascender;
ASLayoutableStyleCallDelegate(ASLayoutableStyleAscenderProperty);
}
- (void)setDescender:(CGFloat)descender
{
ASDN::MutexLocker l(__instanceLock__);
_descender = descender;
ASLayoutableStyleCallDelegate(ASLayoutableStyleDescenderProperty);
}
#pragma mark - ASStaticLayoutable
- (void)setLayoutPosition:(CGPoint)layoutPosition
{
ASDN::MutexLocker l(__instanceLock__);
_layoutPosition = layoutPosition;
ASLayoutableStyleCallDelegate(ASLayoutableStyleLayoutPositionProperty);
}
@end

View File

@@ -0,0 +1,77 @@
//
// ASLayoutableStyleTests.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 <XCTest/XCTest.h>
#import "ASLayoutable.h"
#pragma mark - ASLayoutableStyleTestsDelegate
@interface ASLayoutableStyleTestsDelegate : NSObject<ASLayoutableStyleDelegate>
@property (copy, nonatomic) NSString *propertyNameChanged;
@end
@implementation ASLayoutableStyleTestsDelegate
- (void)style:(id)style propertyDidChange:(NSString *)propertyName
{
self.propertyNameChanged = propertyName;
}
@end
#pragma mark - ASLayoutableStyleTests
@interface ASLayoutableStyleTests : XCTestCase
@end
@implementation ASLayoutableStyleTests
- (void)testSettingSizeProperties
{
ASLayoutableStyle *style = [ASLayoutableStyle new];
style.width = ASDimensionMake(100);
style.height = ASDimensionMake(100);
XCTAssertTrue(ASDimensionEqualToDimension(style.width, ASDimensionMake(100)));
XCTAssertTrue(ASDimensionEqualToDimension(style.height, ASDimensionMake(100)));
}
- (void)testSettingSizeViaHelper
{
ASLayoutableStyle *style = [ASLayoutableStyle new];
[style setSizeWithCGSize:CGSizeMake(100, 100)];
XCTAssertTrue(ASDimensionEqualToDimension(style.width, ASDimensionMake(100)));
XCTAssertTrue(ASDimensionEqualToDimension(style.height, ASDimensionMake(100)));
}
- (void)testSettingExactSize
{
ASLayoutableStyle *style = [ASLayoutableStyle new];
[style setExactSizeWithCGSize:CGSizeMake(100, 100)];
XCTAssertTrue(ASDimensionEqualToDimension(style.minWidth, ASDimensionMake(100)));
XCTAssertTrue(ASDimensionEqualToDimension(style.minHeight, ASDimensionMake(100)));
XCTAssertTrue(ASDimensionEqualToDimension(style.maxWidth, ASDimensionMake(100)));
XCTAssertTrue(ASDimensionEqualToDimension(style.maxHeight, ASDimensionMake(100)));
}
- (void)testSettingPropertiesWillCallDelegate
{
ASLayoutableStyleTestsDelegate *delegate = [ASLayoutableStyleTestsDelegate new];
ASLayoutableStyle *style = [[ASLayoutableStyle alloc] initWithDelegate:delegate];
XCTAssertTrue(ASDimensionEqualToDimension(style.width, ASDimensionAuto));
style.width = ASDimensionMake(100);
XCTAssertTrue(ASDimensionEqualToDimension(style.width, ASDimensionMake(100)));
XCTAssertTrue([delegate.propertyNameChanged isEqualToString:ASLayoutableStyleWidthProperty]);
}
@end

View File

@@ -54,16 +54,16 @@
_rootNode.layoutSpecBlock = ^ASLayoutSpec *(ASDisplayNode * _Nonnull node, ASSizeRange constrainedSize) {
// Layout all nodes absolute in a static layout spec
guitarVideoNode.style.size = ASLayoutableSizeMakeFromCGSize(CGSizeMake(mainScreenBoundsSize.width, mainScreenBoundsSize.height / 3.0));
[guitarVideoNode.style setSizeWithCGSize:CGSizeMake(mainScreenBoundsSize.width, mainScreenBoundsSize.height / 3.0)];
guitarVideoNode.style.layoutPosition = CGPointMake(0, 0);
nicCageVideoNode.style.size = ASLayoutableSizeMakeFromCGSize(CGSizeMake(mainScreenBoundsSize.width/2, mainScreenBoundsSize.height / 3.0));
[nicCageVideoNode.style setSizeWithCGSize:CGSizeMake(mainScreenBoundsSize.width/2, mainScreenBoundsSize.height / 3.0)];
nicCageVideoNode.style.layoutPosition = CGPointMake(mainScreenBoundsSize.width / 2.0, mainScreenBoundsSize.height / 3.0);
simonVideoNode.style.size = ASLayoutableSizeMakeFromCGSize(CGSizeMake(mainScreenBoundsSize.width/2, mainScreenBoundsSize.height / 3.0));
[simonVideoNode.style setSizeWithCGSize:CGSizeMake(mainScreenBoundsSize.width/2, mainScreenBoundsSize.height / 3.0)];
simonVideoNode.style.layoutPosition = CGPointMake(0.0, mainScreenBoundsSize.height - (mainScreenBoundsSize.height / 3.0));
hlsVideoNode.style.size = ASLayoutableSizeMakeFromCGSize(CGSizeMake(mainScreenBoundsSize.width / 2.0, mainScreenBoundsSize.height / 3.0));
[hlsVideoNode.style setSizeWithCGSize:CGSizeMake(mainScreenBoundsSize.width / 2.0, mainScreenBoundsSize.height / 3.0)];
hlsVideoNode.style.layoutPosition = CGPointMake(0.0, mainScreenBoundsSize.height / 3.0);
return [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[guitarVideoNode, nicCageVideoNode, simonVideoNode, hlsVideoNode]];