[Layout] Add style property to ASLayoutable (#2261)

* Add style property to ASLayoutable

* Add styles property to further layout specs

* Adjust some examples

* Add `loadStyle` to create the style object in a ASLayoutable

* Revert "Add `loadStyle` to create the style object in a ASLayoutable"

This reverts commit 2b7240f2c7dc993e38cadf290cfdf08482dd70c7.

* Revert "Adjust some examples"

This reverts commit 3254ae0a321e75db3ecfa80adee9d96bde93a33d.

* Revert "Add styles property to further layout specs"

This reverts commit c779dcb876ead27122c1af1300146a6ad36912cb.

* Rename ASLayoutableStyleDeclaration to ASLayoutableStyle

* Add styleClass class property for extensibility support of the ASLayoutable style object

* flexShrink should not be YES by default
This commit is contained in:
Michael Schneider
2016-09-22 16:00:52 -07:00
committed by GitHub
parent a9857f9963
commit 75dca556e6
24 changed files with 418 additions and 533 deletions

View File

@@ -78,7 +78,7 @@
// of the button node to add a touch handler.
[_titleNode setLayerBacked:YES];
#endif
[_titleNode setFlexShrink:YES];
_titleNode.style.flexShrink = YES;
}
return _titleNode;
}
@@ -517,8 +517,8 @@
#if DEBUG
NSLog(@"Using -[ASDisplayNde preferredFrameSize] is deprecated.");
#endif
stack.width = ASDimensionMake(ASDimensionUnitPoints, self.preferredFrameSize.width);
stack.height = ASDimensionMake(ASDimensionUnitPoints, self.preferredFrameSize.height);
stack.style.width = ASDimensionMake(ASDimensionUnitPoints, self.preferredFrameSize.width);
stack.style.height = ASDimensionMake(ASDimensionUnitPoints, self.preferredFrameSize.height);
spec = [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[stack]];
}
#pragma clang diagnostic pop

View File

@@ -70,14 +70,7 @@ NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp = @"AS
@implementation ASDisplayNode
// Dynamic properties for ASLayoutables
@dynamic layoutableType, size;
// Dynamic properties for sizing
@dynamic width, height, minWidth, maxWidth, minHeight, maxHeight;
// Dynamic properties for stack spec
@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender;
// Dynamic properties for static spec
@dynamic layoutPosition;
@dynamic layoutableType;
@synthesize name = _name;
@synthesize isFinalLayoutable = _isFinalLayoutable;
@@ -307,7 +300,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
_contentsScaleForDisplay = ASScreenScale();
_displaySentinel = [[ASSentinel alloc] init];
_size = ASLayoutableSizeMake();
_style = [[[[self class] styleClass] alloc] init];
_preferredFrameSize = CGSizeZero;
_environmentState = ASEnvironmentStateMakeDefault();
@@ -728,25 +721,20 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
return _flags.layerBacked;
}
#pragma mark - Layout measurement and sizing
#pragma mark - Style
- (ASLayoutableSize)size
+ (Class)styleClass
{
ASDN::MutexLocker l(__instanceLock__);
return _size;
return [ASLayoutableStyle class];
}
- (void)setSize:(ASLayoutableSize)size
- (ASLayoutableStyle *)style
{
ASDN::MutexLocker l(__instanceLock__);
if (ASLayoutableSizeEqualToLayoutableSize(_size, size) == NO) {
_size = size;
[self invalidateCalculatedLayout];
}
return _style;
}
ASLayoutableSizeForwarding
ASLayoutableSizeHelperForwarding
#pragma mark - Layout
- (ASLayout *)layoutThatFits:(ASSizeRange)constrainedSize
{
@@ -770,7 +758,7 @@ ASLayoutableSizeHelperForwarding
// Prepare for layout transition
auto previousLayout = _calculatedDisplayNodeLayout;
auto pendingLayout = std::make_shared<ASDisplayNodeLayout>(
[self calculateLayoutThatFits:constrainedSize restrictedToSize:_size relativeToParentSize:parentSize],
[self calculateLayoutThatFits:constrainedSize restrictedToSize:_style.size relativeToParentSize:parentSize],
constrainedSize,
parentSize
);
@@ -887,7 +875,7 @@ ASLayoutableSizeHelperForwarding
BOOL automaticallyManagesSubnodesDisabled = (self.automaticallyManagesSubnodes == NO);
self.automaticallyManagesSubnodes = YES; // Temporary flag for 1.9.x
newLayout = [self calculateLayoutThatFits:constrainedSize
restrictedToSize:_size
restrictedToSize:_style.size
relativeToParentSize:constrainedSize.max];
if (automaticallyManagesSubnodesDisabled) {
self.automaticallyManagesSubnodes = NO; // Temporary flag for 1.9.x
@@ -2418,7 +2406,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
restrictedToSize:(ASLayoutableSize)size
relativeToParentSize:(CGSize)parentSize
{
const ASSizeRange resolvedRange = ASSizeRangeIntersect(constrainedSize, ASLayoutableSizeResolve(_size, parentSize));
const ASSizeRange resolvedRange = ASSizeRangeIntersect(constrainedSize, ASLayoutableSizeResolve(_style.size, parentSize));
return [self calculateLayoutThatFits:resolvedRange];
}
@@ -2572,8 +2560,8 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
if (! CGSizeEqualToSize(_preferredFrameSize, preferredFrameSize)) {
_preferredFrameSize = preferredFrameSize;
self.width = ASDimensionMake(preferredFrameSize.width);
self.height = ASDimensionMake(preferredFrameSize.height);
self.style.width = ASDimensionMake(preferredFrameSize.width);
self.style.height = ASDimensionMake(preferredFrameSize.height);
[self invalidateCalculatedLayout];
}
@@ -3460,9 +3448,6 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority";
}
}
ASEnvironmentLayoutOptionsForwarding
ASEnvironmentLayoutExtensibilityForwarding
- (ASTraitCollection *)asyncTraitCollection
{
ASDN::MutexLocker l(__instanceLock__);
@@ -3474,6 +3459,8 @@ ASEnvironmentLayoutExtensibilityForwarding
// Subclass override
}
ASEnvironmentLayoutExtensibilityForwarding
#if TARGET_OS_TV
#pragma mark - UIFocusEnvironment Protocol (tvOS)

View File

@@ -372,12 +372,12 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
CGSize size = renderer.size;
if (_attributedText.length > 0) {
self.ascender = [[self class] ascenderWithAttributedString:_attributedText];
self.descender = [[_attributedText attribute:NSFontAttributeName atIndex:_attributedText.length - 1 effectiveRange:NULL] descender];
self.style.ascender = [[self class] ascenderWithAttributedString:_attributedText];
self.style.descender = [[_attributedText attribute:NSFontAttributeName atIndex:_attributedText.length - 1 effectiveRange:NULL] descender];
if (renderer.currentScaleFactor > 0 && renderer.currentScaleFactor < 1.0) {
// while not perfect, this is a good estimate of what the ascender of the scaled font will be.
self.ascender *= renderer.currentScaleFactor;
self.descender *= renderer.currentScaleFactor;
self.style.ascender *= renderer.currentScaleFactor;
self.style.descender *= renderer.currentScaleFactor;
}
}
@@ -431,8 +431,8 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
NSUInteger length = attributedText.length;
if (length > 0) {
self.ascender = [[self class] ascenderWithAttributedString:attributedText];
self.descender = [[attributedText attribute:NSFontAttributeName atIndex:attributedText.length - 1 effectiveRange:NULL] descender];
self.style.ascender = [[self class] ascenderWithAttributedString:attributedText];
self.style.descender = [[attributedText attribute:NSFontAttributeName atIndex:attributedText.length - 1 effectiveRange:NULL] descender];
}
// Tell the display node superclasses that the cached layout is incorrect now

View File

@@ -261,8 +261,8 @@ static NSString * const kRate = @"rate";
}
if (_playerNode) {
_playerNode.width = ASDimensionMake(calculatedSize.width);
_playerNode.height = ASDimensionMake(calculatedSize.height);
_playerNode.style.width = ASDimensionMake(calculatedSize.width);
_playerNode.style.height = ASDimensionMake(calculatedSize.height);
[_playerNode layoutThatFits:ASSizeRangeMake(CGSizeZero, calculatedSize)];
}

View File

@@ -324,8 +324,8 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
{
if (_playbackButtonNode == nil) {
_playbackButtonNode = [[ASDefaultPlaybackButton alloc] init];
_playbackButtonNode.width = ASDimensionMakeWithPoints(16.0);
_playbackButtonNode.height = ASDimensionMakeWithPoints(22.0);
_playbackButtonNode.style.width = ASDimensionMakeWithPoints(16.0);
_playbackButtonNode.style.height = ASDimensionMakeWithPoints(22.0);
if (_delegateFlags.delegatePlaybackButtonTint) {
_playbackButtonNode.tintColor = [_delegate videoPlayerNodePlaybackButtonTint:self];
@@ -406,7 +406,7 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
return slider;
}];
_scrubberNode.flexShrink = YES;
_scrubberNode.style.flexShrink = YES;
[_cachedControls setObject:_scrubberNode forKey:@(ASVideoPlayerNodeControlTypeScrubber)];
}
@@ -418,7 +418,7 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
{
if (_controlFlexGrowSpacerSpec == nil) {
_controlFlexGrowSpacerSpec = [[ASStackLayoutSpec alloc] init];
_controlFlexGrowSpacerSpec.flexGrow = YES;
_controlFlexGrowSpacerSpec.style.flexGrow = YES;
}
[_cachedControls setObject:_controlFlexGrowSpacerSpec forKey:@(ASVideoPlayerNodeControlTypeFlexGrowSpacer)];
@@ -601,8 +601,8 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
return spinnnerView;
}];
_spinnerNode.width = ASDimensionMakeWithPoints(44.0);
_spinnerNode.height = ASDimensionMakeWithPoints(44.0);
_spinnerNode.style.width = ASDimensionMakeWithPoints(44.0);
_spinnerNode.style.height = ASDimensionMakeWithPoints(44.0);
[self addSubnode:_spinnerNode];
[self setNeedsLayout];
@@ -705,7 +705,7 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
ASDisplayNodeAssert(NO, @"Infinite width or height in ASVideoPlayerNode");
maxSize = CGSizeZero;
}
_videoNode.size = ASLayoutableSizeMakeFromCGSize(maxSize);
_videoNode.style.size = ASLayoutableSizeMakeFromCGSize(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.size = ASLayoutableSizeMakeFromCGSize(maxSize);
centerLayoutSpec.style.size = ASLayoutableSizeMakeFromCGSize(maxSize);
[children addObject:centerLayoutSpec];
}
ASOverlayLayoutSpec *overlaySpec = [ASOverlayLayoutSpec overlayLayoutSpecWithChild:_videoNode overlay:layoutSpec];
overlaySpec.size = ASLayoutableSizeMakeFromCGSize(maxSize);
overlaySpec.style.size = ASLayoutableSizeMakeFromCGSize(maxSize);
[children addObject:overlaySpec];
return [ASStaticLayoutSpec staticLayoutSpecWithChildren:children];
@@ -731,24 +731,24 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
- (ASLayoutSpec *)defaultLayoutSpecThatFits:(CGSize)maxSize
{
_scrubberNode.width = ASDimensionMakeWithPoints(maxSize.width);
_scrubberNode.height = ASDimensionMakeWithPoints(44.0);
_scrubberNode.style.width = ASDimensionMakeWithPoints(maxSize.width);
_scrubberNode.style.height = ASDimensionMakeWithPoints(44.0);
ASLayoutSpec *spacer = [[ASLayoutSpec alloc] init];
spacer.flexGrow = YES;
spacer.style.flexGrow = YES;
ASStackLayoutSpec *controlbarSpec = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal
spacing:10.0
justifyContent:ASStackLayoutJustifyContentStart
alignItems:ASStackLayoutAlignItemsCenter
children: [self controlsForLayoutSpec] ];
controlbarSpec.alignSelf = ASStackLayoutAlignSelfStretch;
controlbarSpec.style.alignSelf = ASStackLayoutAlignSelfStretch;
UIEdgeInsets insets = UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0);
ASInsetLayoutSpec *controlbarInsetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:controlbarSpec];
controlbarInsetSpec.alignSelf = ASStackLayoutAlignSelfStretch;
controlbarInsetSpec.style.alignSelf = ASStackLayoutAlignSelfStretch;
ASStackLayoutSpec *mainVerticalStack = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical
spacing:0.0

View File

@@ -26,23 +26,16 @@ typedef std::map<unsigned long, id<ASLayoutable>, std::less<unsigned long>> ASCh
@interface ASLayoutSpec() {
ASDN::RecursiveMutex __instanceLock__;
ASLayoutableSize _size;
ASEnvironmentState _environmentState;
ASChildMap _children;
ASEnvironmentState _environmentState;
ASLayoutableStyle *_style;
}
@end
@implementation ASLayoutSpec
// Dynamic properties for ASLayoutables
@dynamic layoutableType, size;
// Dynamic properties for sizing
@dynamic width, height, minWidth, maxWidth, minHeight, maxHeight;
// Dynamic properties for stack spec
@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender;
// Dynamic properties for static spec
@dynamic layoutPosition;
@dynamic layoutableType;
@synthesize isFinalLayoutable = _isFinalLayoutable;
#pragma mark - Class
@@ -63,9 +56,11 @@ typedef std::map<unsigned long, id<ASLayoutable>, std::less<unsigned long>> ASCh
if (!(self = [super init])) {
return nil;
}
_isMutable = YES;
_size = ASLayoutableSizeMake();
_environmentState = ASEnvironmentStateMakeDefault();
_style = [[[[self class] styleClass] alloc] init];
return self;
}
@@ -79,25 +74,19 @@ typedef std::map<unsigned long, id<ASLayoutable>, std::less<unsigned long>> ASCh
return YES;
}
#pragma mark - Style
#pragma mark - Sizing
- (ASLayoutableSize)size
+ (Class)styleClass
{
ASDN::MutexLocker l(__instanceLock__);
return _size;
return [ASLayoutableStyle class];
}
- (void)setSize:(ASLayoutableSize)size
- (ASLayoutableStyle *)style
{
ASDN::MutexLocker l(__instanceLock__);
_size = size;
return _style;
}
ASLayoutableSizeForwarding
ASLayoutableSizeHelperForwarding
#pragma mark - Layout
// Deprecated
@@ -113,14 +102,14 @@ ASLayoutableSizeHelperForwarding
- (ASLayout *)layoutThatFits:(ASSizeRange)constrainedSize parentSize:(CGSize)parentSize
{
return [self calculateLayoutThatFits:constrainedSize restrictedToSize:_size relativeToParentSize:parentSize];
return [self calculateLayoutThatFits:constrainedSize restrictedToSize:_style.size relativeToParentSize:parentSize];
}
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
restrictedToSize:(ASLayoutableSize)size
relativeToParentSize:(CGSize)parentSize
{
const ASSizeRange resolvedRange = ASSizeRangeIntersect(constrainedSize, ASLayoutableSizeResolve(_size, parentSize));
const ASSizeRange resolvedRange = ASSizeRangeIntersect(constrainedSize, ASLayoutableSizeResolve(_style.size, parentSize));
return [self calculateLayoutThatFits:resolvedRange];
}
@@ -285,15 +274,14 @@ ASLayoutableSizeHelperForwarding
_environmentState.environmentTraitCollection = environmentTraitCollection;
}
ASEnvironmentLayoutOptionsForwarding
ASEnvironmentLayoutExtensibilityForwarding
- (ASTraitCollection *)asyncTraitCollection
{
ASDN::MutexLocker l(__instanceLock__);
return [ASTraitCollection traitCollectionWithASEnvironmentTraitCollection:self.environmentTraitCollection];
}
ASEnvironmentLayoutExtensibilityForwarding
@end

View File

@@ -72,7 +72,7 @@ static NSString *ASLayoutValidationWrappingAssertMessage(SEL selector, id obj, C
Class stackContainerClass = [ASStaticLayoutSpec class];
// Check for default layoutPosition
if (!CGPointEqualToPoint(sublayoutLayoutable.layoutPosition, CGPointZero)) {
if (!CGPointEqualToPoint(sublayoutLayoutable.style.layoutPosition, CGPointZero)) {
assertMessage = ASLayoutValidationWrappingAssertMessage(@selector(layoutPosition), sublayoutLayoutable, stackContainerClass);
}
@@ -104,17 +104,17 @@ static NSString *ASLayoutValidationWrappingAssertMessage(SEL selector, id obj, C
Class stackContainerClass = [ASStackLayoutSpec class];
// Check if default values related to ASStackLayoutSpec have changed
if (sublayoutLayoutable.spacingBefore != 0) {
if (sublayoutLayoutable.style.spacingBefore != 0) {
assertMessage = ASLayoutValidationWrappingAssertMessage(@selector(spacingBefore), sublayoutLayoutable, stackContainerClass);
} else if (sublayoutLayoutable.spacingAfter != 0) {
} else if (sublayoutLayoutable.style.spacingAfter != 0) {
assertMessage = ASLayoutValidationWrappingAssertMessage(@selector(spacingAfter), sublayoutLayoutable, stackContainerClass);
} else if (sublayoutLayoutable.flexGrow == YES) {
} else if (sublayoutLayoutable.style.flexGrow == YES) {
assertMessage = ASLayoutValidationWrappingAssertMessage(@selector(flexGrow), sublayoutLayoutable, stackContainerClass);
} else if (sublayoutLayoutable.flexShrink == YES) {
} else if (sublayoutLayoutable.style.flexShrink == YES) {
assertMessage = ASLayoutValidationWrappingAssertMessage(@selector(flexShrink), sublayoutLayoutable, stackContainerClass);
} else if (!ASDimensionEqualToDimension(sublayoutLayoutable.flexBasis, ASDimensionAuto) ) {
} else if (!ASDimensionEqualToDimension(sublayoutLayoutable.style.flexBasis, ASDimensionAuto) ) {
assertMessage = ASLayoutValidationWrappingAssertMessage(@selector(flexBasis), sublayoutLayoutable, stackContainerClass);
} else if (sublayoutLayoutable.alignSelf != ASStackLayoutAlignSelfAuto) {
} else if (sublayoutLayoutable.style.alignSelf != ASStackLayoutAlignSelfAuto) {
assertMessage = ASLayoutValidationWrappingAssertMessage(@selector(alignSelf), sublayoutLayoutable, stackContainerClass);
}

View File

@@ -50,7 +50,9 @@ 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 ASLayoutable <ASEnvironment, ASStackLayoutable, ASStaticLayoutable, ASLayoutablePrivate, ASLayoutableExtensibility>
@protocol ASLayoutable <ASEnvironment, ASLayoutablePrivate, ASLayoutableExtensibility>
#pragma mark - Getter
/**
* @abstract Returns type of layoutable
@@ -62,63 +64,19 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, assign, readonly) BOOL canLayoutAsynchronous;
#pragma mark - Sizing
/**
* @abstract A size constraint that should apply to this ASLayoutable.
*/
@property (nonatomic, assign, readonly) ASLayoutableStyle *style;
/**
* @abstract The width property specifies the height of the content area of an ASLayoutable.
* The minWidth and maxWidth properties override width.
* Defaults to ASRelativeDimensionTypeAuto
*/
@property (nonatomic, assign, readwrite) ASDimension width;
/**
* @abstract The height property specifies the height of the content area of an ASLayoutable
* The minHeight and maxHeight properties override height.
* Defaults to ASDimensionTypeAuto
*/
@property (nonatomic, assign, readwrite) ASDimension height;
/**
* @abstract The minHeight property is used to set the minimum height of a given element. It prevents the used value
* of the height property from becoming smaller than the value specified for minHeight.
* The value of minHeight overrides both maxHeight and height.
* Defaults to ASDimensionTypeAuto
*/
@property (nonatomic, assign, readwrite) ASDimension minHeight;
/**
* @abstract The maxHeight property is used to set the maximum height of an element. It prevents the used value of the
* height property from becoming larger than the value specified for maxHeight.
* The value of maxHeight overrides height, but minHeight overrides maxHeight.
* Defaults to ASDimensionTypeAuto
*/
@property (nonatomic, assign, readwrite) ASDimension maxHeight;
/**
* @abstract The minWidth property is used to set the minimum width of a given element. It prevents the used value of
* the width property from becoming smaller than the value specified for minWidth.
* The value of minWidth overrides both maxWidth and width.
* Defaults to ASDimensionTypeAuto
*/
@property (nonatomic, assign, readwrite) ASDimension minWidth;
/**
* @abstract The maxWidth property is used to set the maximum width of a given element. It prevents the used value of
* the width property from becoming larger than the value specified for maxWidth.
* The value of maxWidth overrides width, but minWidth overrides maxWidth.
* Defaults to ASDimensionTypeAuto
*/
@property (nonatomic, assign, readwrite) ASDimension maxWidth;
/**
* @abstract Set max and width properties from given size
*/
- (void)setSizeWithCGSize:(CGSize)size;
/**
* @abstract Set minHeight, maxHeight and minWidth, maxWidth properties from given size
*/
- (void)setExactSizeWithCGSize:(CGSize)size;
* @discussion This property contains the ASLayoutableStyle class object by default. Subclasses can use this property to
* return a different size class as needed. For example, if your layoutable would like extend the style object to support
* more properties you might want to set this property to a custom subclass of ASLayoutableStyle.
*
* This property is set only once early in the creation of the layoutable to create the corresponding style object.
*/
@property (class, nonatomic, readonly) Class styleClass;
#pragma mark - Calculate layout
@@ -187,67 +145,6 @@ NS_ASSUME_NONNULL_BEGIN
relativeToParentSize:(CGSize)parentSize;
#pragma mark - Layout options from the Layoutable Protocols
#pragma mark - ASStackLayoutable
/**
* @abstract Additional space to place before this object in the stacking direction.
* Used when attached to a stack layout.
*/
@property (nonatomic, readwrite) CGFloat spacingBefore;
/**
* @abstract Additional space to place after this object in the stacking direction.
* Used when attached to a stack layout.
*/
@property (nonatomic, readwrite) CGFloat spacingAfter;
/**
* @abstract If the sum of childrens' stack dimensions is less than the minimum size, should this object grow?
* Used when attached to a stack layout.
*/
@property (nonatomic, readwrite) BOOL flexGrow;
/**
* @abstract If the sum of childrens' stack dimensions is greater than the maximum size, should this object shrink?
* Used when attached to a stack layout.
*/
@property (nonatomic, readwrite) BOOL flexShrink;
/**
* @abstract Specifies the initial size in the stack dimension for this object.
* Default to ASRelativeDimensionAuto
* Used when attached to a stack layout.
*/
@property (nonatomic, readwrite) ASDimension flexBasis;
/**
* @abstract Orientation of the object along cross axis, overriding alignItems
* Used when attached to a stack layout.
*/
@property (nonatomic, readwrite) ASStackLayoutAlignSelf alignSelf;
/**
* @abstract Used for baseline alignment. The distance from the top of the object to its baseline.
*/
@property (nonatomic, readwrite) CGFloat ascender;
/**
* @abstract Used for baseline alignment. The distance from the baseline of the object to its bottom.
*/
@property (nonatomic, readwrite) CGFloat descender;
#pragma mark - ASStaticLayoutable
/**
* @abstract The position of this object within its parent spec.
*/
@property (nonatomic, assign) CGPoint layoutPosition;
#pragma mark - Deprecated
/**
@@ -263,4 +160,133 @@ NS_ASSUME_NONNULL_BEGIN
@end
#pragma mark - ASLayoutableStyle
@interface ASLayoutableStyle : NSObject <ASStackLayoutable, ASStaticLayoutable>
#pragma mark - Sizing
// TODO: Move to internal method?
/**
* @abstract A size constraint that should apply to this ASLayoutable.
*/
@property (nonatomic, assign, readwrite) ASLayoutableSize size;
/**
* @abstract The width property specifies the height of the content area of an ASLayoutable.
* The minWidth and maxWidth properties override width.
* Defaults to ASRelativeDimensionTypeAuto
*/
@property (nonatomic, assign, readwrite) ASDimension width;
/**
* @abstract The height property specifies the height of the content area of an ASLayoutable
* The minHeight and maxHeight properties override height.
* Defaults to ASDimensionTypeAuto
*/
@property (nonatomic, assign, readwrite) ASDimension height;
/**
* @abstract The minHeight property is used to set the minimum height of a given element. It prevents the used value
* of the height property from becoming smaller than the value specified for minHeight.
* The value of minHeight overrides both maxHeight and height.
* Defaults to ASDimensionTypeAuto
*/
@property (nonatomic, assign, readwrite) ASDimension minHeight;
/**
* @abstract The maxHeight property is used to set the maximum height of an element. It prevents the used value of the
* height property from becoming larger than the value specified for maxHeight.
* The value of maxHeight overrides height, but minHeight overrides maxHeight.
* Defaults to ASDimensionTypeAuto
*/
@property (nonatomic, assign, readwrite) ASDimension maxHeight;
/**
* @abstract The minWidth property is used to set the minimum width of a given element. It prevents the used value of
* the width property from becoming smaller than the value specified for minWidth.
* The value of minWidth overrides both maxWidth and width.
* Defaults to ASDimensionTypeAuto
*/
@property (nonatomic, assign, readwrite) ASDimension minWidth;
/**
* @abstract The maxWidth property is used to set the maximum width of a given element. It prevents the used value of
* the width property from becoming larger than the value specified for maxWidth.
* The value of maxWidth overrides width, but minWidth overrides maxWidth.
* Defaults to ASDimensionTypeAuto
*/
@property (nonatomic, assign, readwrite) ASDimension maxWidth;
/**
* @abstract Set max and width properties from given size
*/
- (void)setSizeWithCGSize:(CGSize)size;
/**
* @abstract Set minHeight, maxHeight and minWidth, maxWidth properties from given size
*/
- (void)setExactSizeWithCGSize:(CGSize)size;
#pragma mark - ASStackLayoutable
/**
* @abstract Additional space to place before this object in the stacking direction.
* Used when attached to a stack layout.
*/
@property (nonatomic, assign) CGFloat spacingBefore;
/**
* @abstract Additional space to place after this object in the stacking direction.
* Used when attached to a stack layout.
*/
@property (nonatomic, assign) CGFloat spacingAfter;
/**
* @abstract If the sum of childrens' stack dimensions is less than the minimum size, should this object grow?
* Used when attached to a stack layout.
*/
@property (nonatomic, assign) BOOL flexGrow;
/**
* @abstract If the sum of childrens' stack dimensions is greater than the maximum size, should this object shrink?
* Used when attached to a stack layout.
*/
@property (nonatomic, assign) BOOL flexShrink;
/**
* @abstract Specifies the initial size in the stack dimension for this object.
* Default to ASRelativeDimensionAuto
* Used when attached to a stack layout.
*/
@property (nonatomic, assign) ASDimension flexBasis;
/**
* @abstract Orientation of the object along cross axis, overriding alignItems
* Used when attached to a stack layout.
*/
@property (nonatomic, assign) ASStackLayoutAlignSelf alignSelf;
/**
* @abstract Used for baseline alignment. The distance from the top of the object to its baseline.
*/
@property (nonatomic, assign) CGFloat ascender;
/**
* @abstract Used for baseline alignment. The distance from the baseline of the object to its bottom.
*/
@property (nonatomic, assign) CGFloat descender;
#pragma mark - ASStaticLayoutable
/**
* @abstract The position of this object within its parent spec.
*/
@property (nonatomic, assign) CGPoint layoutPosition;
@end
NS_ASSUME_NONNULL_END

View File

@@ -13,6 +13,7 @@
#import "ASLayoutablePrivate.h"
#import "ASEnvironmentInternal.h"
#import "ASDisplayNodeInternal.h"
#import "ASThread.h"
#import <map>
@@ -82,3 +83,113 @@ void ASLayoutableClearCurrentContext()
ASDN::StaticMutexLocker l(_layoutableContextLock);
layoutableContextMap.erase(key);
}
#pragma mark - ASLayoutableStyle
@implementation ASLayoutableStyle {
ASDN::RecursiveMutex __instanceLock__;
}
@dynamic width, height, minWidth, maxWidth, minHeight, maxHeight;
- (instancetype)init
{
self = [super init];
if (self) {
_size = ASLayoutableSizeMake();
}
return self;
}
#pragma mark - ASLayoutableSizeForwarding
- (ASDimension)width
{
ASDN::MutexLocker l(__instanceLock__);
return _size.width;
}
- (void)setWidth:(ASDimension)width
{
ASDN::MutexLocker l(__instanceLock__);
_size.width = width;
}
- (ASDimension)height
{
ASDN::MutexLocker l(__instanceLock__);
return _size.height;
}
- (void)setHeight:(ASDimension)height
{
ASDN::MutexLocker l(__instanceLock__);
_size.height = height;
}
- (ASDimension)minWidth
{
ASDN::MutexLocker l(__instanceLock__);
return _size.minWidth;
}
- (void)setMinWidth:(ASDimension)minWidth
{
ASDN::MutexLocker l(__instanceLock__);
_size.minWidth = minWidth;
}
- (ASDimension)maxWidth
{
ASDN::MutexLocker l(__instanceLock__);
return _size.maxWidth;
}
- (void)setMaxWidth:(ASDimension)maxWidth
{
ASDN::MutexLocker l(__instanceLock__);
_size.maxWidth = maxWidth;
}
- (ASDimension)minHeight
{
ASDN::MutexLocker l(__instanceLock__);
return _size.minHeight;
}
- (void)setMinHeight:(ASDimension)minHeight
{
ASDN::MutexLocker l(__instanceLock__);
_size.minHeight = minHeight;
}
- (ASDimension)maxHeight
{
ASDN::MutexLocker l(__instanceLock__);
return _size.maxHeight;
}
- (void)setMaxHeight:(ASDimension)maxHeight
{
ASDN::MutexLocker l(__instanceLock__);
_size.maxHeight = maxHeight;
}
#pragma mark - Layout measurement and sizing
- (void)setSizeWithCGSize:(CGSize)size
{
self.width = ASDimensionMakeWithPoints(size.width);
self.height = ASDimensionMakeWithPoints(size.height);
}
- (void)setExactSizeWithCGSize:(CGSize)size
{
self.minWidth = ASDimensionMakeWithPoints(size.width);
self.minHeight = ASDimensionMakeWithPoints(size.height);
self.maxWidth = ASDimensionMakeWithPoints(size.width);
self.maxHeight = ASDimensionMakeWithPoints(size.height);
}
@end

View File

@@ -10,8 +10,8 @@
#import "ASDimension.h"
@class ASLayoutSpec;
@protocol ASLayoutable;
@class ASLayoutableStyle;
struct ASLayoutableContext {
int32_t transitionID;
@@ -40,11 +40,6 @@ extern void ASLayoutableClearCurrentContext();
*/
@protocol ASLayoutablePrivate <NSObject>
/**
* @abstract A size constraint that should apply to this ASLayoutable.
*/
@property (nonatomic, assign, readwrite) ASLayoutableSize size;
/**
* @abstract This method can be used to give the user a chance to wrap an ASLayoutable in an ASLayoutSpec
* just before it is added to a parent ASLayoutSpec. For example, if you wanted an ASTextNode that was always
@@ -66,228 +61,6 @@ extern void ASLayoutableClearCurrentContext();
@end
#pragma mark - ASLayoutableForwarding
/**
* Both an ASDisplayNode and an ASLayoutSpec conform to ASLayoutable. There are several properties
* in ASLayoutable that are used when a node or spec is used in a layout spec.
* These properties are provided for convenience, as they are forwards to the node or spec's
* properties. Instead of duplicating the property forwarding in both classes, we
* create a define that allows us to easily implement the forwards in one place.
*
* If you create a custom layout spec, we recommend this stragety if you decide to extend
* ASDisplayNode and ASLayoutSpec to provide convenience properties for any options that your
* layoutSpec may require.
*/
#pragma mark - ASLayoutableSizeForwarding
#define ASLayoutableSizeForwarding \
\
- (ASDimension)width\
{\
ASDN::MutexLocker l(__instanceLock__);\
return _size.width;\
}\
\
- (void)setWidth:(ASDimension)width\
{\
ASDN::MutexLocker l(__instanceLock__);\
_size.width = width;\
}\
\
- (ASDimension)height\
{\
ASDN::MutexLocker l(__instanceLock__);\
return _size.height;\
}\
\
- (void)setHeight:(ASDimension)height\
{\
ASDN::MutexLocker l(__instanceLock__);\
_size.height = height;\
}\
\
- (ASDimension)minWidth\
{\
ASDN::MutexLocker l(__instanceLock__);\
return _size.minWidth;\
}\
\
- (void)setMinWidth:(ASDimension)minWidth\
{\
ASDN::MutexLocker l(__instanceLock__);\
_size.minWidth = minWidth;\
}\
\
- (ASDimension)maxWidth\
{\
ASDN::MutexLocker l(__instanceLock__);\
return _size.maxWidth;\
}\
\
- (void)setMaxWidth:(ASDimension)maxWidth\
{\
ASDN::MutexLocker l(__instanceLock__);\
_size.maxWidth = maxWidth;\
}\
\
- (ASDimension)minHeight\
{\
ASDN::MutexLocker l(__instanceLock__);\
return _size.minHeight;\
}\
\
- (void)setMinHeight:(ASDimension)minHeight\
{\
ASDN::MutexLocker l(__instanceLock__);\
_size.minHeight = minHeight;\
}\
\
- (ASDimension)maxHeight\
{\
ASDN::MutexLocker l(__instanceLock__);\
return _size.maxHeight;\
}\
\
- (void)setMaxHeight:(ASDimension)maxHeight\
{\
ASDN::MutexLocker l(__instanceLock__);\
_size.maxHeight = maxHeight;\
}\
#pragma mark - ASLayoutableSizeHelperForwarding
#define ASLayoutableSizeHelperForwarding \
- (void)setSizeWithCGSize:(CGSize)size\
{\
self.width = ASDimensionMakeWithPoints(size.width);\
self.height = ASDimensionMakeWithPoints(size.height);\
}\
\
- (void)setExactSizeWithCGSize:(CGSize)size\
{\
self.minWidth = ASDimensionMakeWithPoints(size.width);\
self.minHeight = ASDimensionMakeWithPoints(size.height);\
self.maxWidth = ASDimensionMakeWithPoints(size.width);\
self.maxHeight = ASDimensionMakeWithPoints(size.height);\
}\
#pragma mark - ASLayoutOptionsForwarding
#define ASEnvironmentLayoutOptionsForwarding \
- (void)propagateUpLayoutOptionsState\
{\
if (!ASEnvironmentStatePropagationEnabled()) {\
return;\
}\
id<ASEnvironment> parent = [self parent];\
if ([parent supportsUpwardPropagation]) {\
ASEnvironmentStatePropagateUp(parent, _environmentState.layoutOptionsState);\
}\
}\
\
- (CGFloat)spacingAfter\
{\
return _environmentState.layoutOptionsState.spacingAfter;\
}\
\
- (void)setSpacingAfter:(CGFloat)spacingAfter\
{\
_environmentState.layoutOptionsState.spacingAfter = spacingAfter;\
[self propagateUpLayoutOptionsState];\
}\
\
- (CGFloat)spacingBefore\
{\
return _environmentState.layoutOptionsState.spacingBefore;\
}\
\
- (void)setSpacingBefore:(CGFloat)spacingBefore\
{\
_environmentState.layoutOptionsState.spacingBefore = spacingBefore;\
[self propagateUpLayoutOptionsState];\
}\
\
- (BOOL)flexGrow\
{\
return _environmentState.layoutOptionsState.flexGrow;\
}\
\
- (void)setFlexGrow:(BOOL)flexGrow\
{\
_environmentState.layoutOptionsState.flexGrow = flexGrow;\
[self propagateUpLayoutOptionsState];\
}\
\
- (BOOL)flexShrink\
{\
return _environmentState.layoutOptionsState.flexShrink;\
}\
\
- (void)setFlexShrink:(BOOL)flexShrink\
{\
_environmentState.layoutOptionsState.flexShrink = flexShrink;\
[self propagateUpLayoutOptionsState];\
}\
\
- (ASDimension)flexBasis\
{\
return _environmentState.layoutOptionsState.flexBasis;\
}\
\
- (void)setFlexBasis:(ASDimension)flexBasis\
{\
_environmentState.layoutOptionsState.flexBasis = flexBasis;\
[self propagateUpLayoutOptionsState];\
}\
\
- (ASStackLayoutAlignSelf)alignSelf\
{\
return _environmentState.layoutOptionsState.alignSelf;\
}\
\
- (void)setAlignSelf:(ASStackLayoutAlignSelf)alignSelf\
{\
_environmentState.layoutOptionsState.alignSelf = alignSelf;\
[self propagateUpLayoutOptionsState];\
}\
\
- (CGFloat)ascender\
{\
return _environmentState.layoutOptionsState.ascender;\
}\
\
- (void)setAscender:(CGFloat)ascender\
{\
_environmentState.layoutOptionsState.ascender = ascender;\
[self propagateUpLayoutOptionsState];\
}\
\
- (CGFloat)descender\
{\
return _environmentState.layoutOptionsState.descender;\
}\
\
- (void)setDescender:(CGFloat)descender\
{\
_environmentState.layoutOptionsState.descender = descender;\
[self propagateUpLayoutOptionsState];\
}\
\
- (CGPoint)layoutPosition\
{\
return _environmentState.layoutOptionsState.layoutPosition;\
}\
\
- (void)setLayoutPosition:(CGPoint)layoutPosition\
{\
_environmentState.layoutOptionsState.layoutPosition = layoutPosition;\
[self propagateUpLayoutOptionsState];\
}\
#pragma mark - ASLayoutableExtensibility
#define ASEnvironmentLayoutExtensibilityForwarding \

View File

@@ -143,12 +143,12 @@
const auto baselinePositionedLayout = ASStackBaselinePositionedLayout::compute(positionedLayout, style, constrainedSize);
if (self.direction == ASStackLayoutDirectionVertical) {
ASDN::MutexLocker l(__instanceLock__);
self.ascender = [stackChildren.front() ascender];
self.descender = [stackChildren.back() descender];
self.style.ascender = stackChildren.front().style.ascender;
self.style.descender = stackChildren.back().style.descender;
} else {
ASDN::MutexLocker l(__instanceLock__);
self.ascender = baselinePositionedLayout.ascender;
self.descender = baselinePositionedLayout.descender;
self.style.ascender = baselinePositionedLayout.ascender;
self.style.descender = baselinePositionedLayout.descender;
}
if (needsBaselinePass) {

View File

@@ -46,13 +46,13 @@
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:children.count];
for (id<ASLayoutable> child in children) {
CGPoint layoutPosition = child.layoutPosition;
CGPoint layoutPosition = child.style.layoutPosition;
CGSize autoMaxSize = {
constrainedSize.max.width - layoutPosition.x,
constrainedSize.max.height - layoutPosition.y
};
const ASSizeRange childConstraint = ASLayoutableSizeResolveAutoSize(child.size, size, {{0,0}, autoMaxSize});
const ASSizeRange childConstraint = ASLayoutableSizeResolveAutoSize(child.style.size, size, {{0,0}, autoMaxSize});
ASLayout *sublayout = [child layoutThatFits:childConstraint parentSize:size];
sublayout.position = layoutPosition;

View File

@@ -106,7 +106,7 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
@protected
ASDisplayNode * __weak _supernode;
ASLayoutableSize _size;
ASLayoutableStyle *_style;
CGSize _preferredFrameSize;
ASSentinel *_displaySentinel;

View File

@@ -18,9 +18,9 @@ static CGFloat baselineForItem(const ASStackLayoutSpecStyle &style,
__weak id<ASLayoutable> child = layout.layoutable;
switch (style.alignItems) {
case ASStackLayoutAlignItemsBaselineFirst:
return child.ascender;
return child.style.ascender;
case ASStackLayoutAlignItemsBaselineLast:
return layout.size.height + child.descender;
return layout.size.height + child.style.descender;
default:
return 0;
}
@@ -36,7 +36,7 @@ static CGFloat baselineOffset(const ASStackLayoutSpecStyle &style,
__weak id<ASLayoutable> child = l.layoutable;
switch (style.alignItems) {
case ASStackLayoutAlignItemsBaselineFirst:
return maxAscender - child.ascender;
return maxAscender - child.style.ascender;
case ASStackLayoutAlignItemsBaselineLast:
return maxBaseline - baselineForItem(style, l);
@@ -89,9 +89,9 @@ ASStackBaselinePositionedLayout ASStackBaselinePositionedLayout::compute(const A
our layoutSpec to have it so that it can be baseline aligned with another text node or baseline layout spec.
*/
const auto ascenderIt = std::max_element(positionedLayout.sublayouts.begin(), positionedLayout.sublayouts.end(), [&](const ASLayout *a, const ASLayout *b){
return a.layoutable.ascender < b.layoutable.ascender;
return a.layoutable.style.ascender < b.layoutable.style.ascender;
});
const CGFloat maxAscender = ascenderIt == positionedLayout.sublayouts.end() ? 0 : (*ascenderIt).layoutable.ascender;
const CGFloat maxAscender = ascenderIt == positionedLayout.sublayouts.end() ? 0 : (*ascenderIt).layoutable.style.ascender;
/*
Step 3: Take each child and update its layout position based on the baseline offset.
@@ -109,7 +109,7 @@ ASStackBaselinePositionedLayout ASStackBaselinePositionedLayout::compute(const A
BOOL first = YES;
stackedChildren = AS::map(positionedLayout.sublayouts, [&](ASLayout *l) -> ASLayout *{
__weak id<ASLayoutable> child = l.layoutable;
p = p + directionPoint(style.direction, child.spacingBefore, 0);
p = p + directionPoint(style.direction, child.style.spacingBefore, 0);
if (first) {
// if this is the first item use the previously computed start point
p = l.position;
@@ -126,9 +126,9 @@ ASStackBaselinePositionedLayout ASStackBaselinePositionedLayout::compute(const A
// node from baselines and not bounding boxes.
CGFloat spacingAfterBaseline = 0;
if (style.direction == ASStackLayoutDirectionVertical) {
spacingAfterBaseline = child.descender;
spacingAfterBaseline = child.style.descender;
}
p = p + directionPoint(style.direction, stackDimension(style.direction, l.size) + child.spacingAfter + spacingAfterBaseline, 0);
p = p + directionPoint(style.direction, stackDimension(style.direction, l.size) + child.style.spacingAfter + spacingAfterBaseline, 0);
return l;
});
@@ -161,7 +161,7 @@ ASStackBaselinePositionedLayout ASStackBaselinePositionedLayout::compute(const A
const auto descenderIt = std::max_element(stackedChildren.begin(), stackedChildren.end(), [&](const ASLayout *a, const ASLayout *b){
return a.position.y + a.size.height < b.position.y + b.size.height;
});
const CGFloat minDescender = descenderIt == stackedChildren.end() ? 0 : (*descenderIt).layoutable.descender;
const CGFloat minDescender = descenderIt == stackedChildren.end() ? 0 : (*descenderIt).layoutable.style.descender;
return {stackedChildren, crossSize, maxAscender, minDescender};
}

View File

@@ -19,7 +19,7 @@ static CGFloat crossOffset(const ASStackLayoutSpecStyle &style,
const ASStackUnpositionedItem &l,
const CGFloat crossSize)
{
switch (alignment(l.child.alignSelf, style.alignItems)) {
switch (alignment(l.child.style.alignSelf, style.alignItems)) {
case ASStackLayoutAlignItemsEnd:
return crossSize - crossDimension(style.direction, l.layout.size);
case ASStackLayoutAlignItemsCenter:
@@ -66,14 +66,14 @@ static ASStackPositionedLayout stackedLayout(const ASStackLayoutSpecStyle &style
auto stackedChildren = AS::map(unpositionedLayout.items, [&](const ASStackUnpositionedItem &l) -> ASLayout *{
offset = (l.child == lastChild) ? lastChildOffset : 0;
p = p + directionPoint(style.direction, l.child.spacingBefore + offset, 0);
p = p + directionPoint(style.direction, l.child.style.spacingBefore + offset, 0);
if (!first) {
p = p + directionPoint(style.direction, style.spacing + extraSpacing, 0);
}
first = NO;
l.layout.position = p + directionPoint(style.direction, 0, crossOffset(style, l, crossSize));
p = p + directionPoint(style.direction, stackDimension(style.direction, l.layout.size) + l.child.spacingAfter, 0);
p = p + directionPoint(style.direction, stackDimension(style.direction, l.layout.size) + l.child.style.spacingAfter, 0);
return l.layout;
});
return {stackedChildren, crossSize};

View File

@@ -26,7 +26,7 @@ static ASLayout *crossChildLayout(const id<ASLayoutable> child,
const CGFloat crossMax,
const CGSize size)
{
const ASStackLayoutAlignItems alignItems = alignment(child.alignSelf, style.alignItems);
const ASStackLayoutAlignItems alignItems = alignment(child.style.alignSelf, style.alignItems);
// stretched children will have a cross dimension of at least crossMin
const CGFloat childCrossMin = alignItems == ASStackLayoutAlignItemsStretch ? crossMin : 0;
const ASSizeRange childSizeRange = directionSizeRange(style.direction, stackMin, stackMax, childCrossMin, crossMax);
@@ -79,7 +79,7 @@ static void stretchChildrenAlongCrossDimension(std::vector<ASStackUnpositionedIt
const CGFloat childCrossMax = it == layouts.end() ? 0 : crossDimension(style.direction, it->layout.size);
for (auto &l : layouts) {
const ASStackLayoutAlignItems alignItems = alignment(l.child.alignSelf, style.alignItems);
const ASStackLayoutAlignItems alignItems = alignment(l.child.style.alignSelf, style.alignItems);
const CGFloat cross = crossDimension(style.direction, l.layout.size);
const CGFloat stack = stackDimension(style.direction, l.layout.size);
@@ -116,7 +116,7 @@ static CGFloat computeStackDimensionSum(const std::vector<ASStackUnpositionedIte
children.empty() ? 0 : style.spacing * (children.size() - 1),
[&](CGFloat x, const ASStackUnpositionedItem &l) {
const id<ASLayoutable> child = l.child;
return x + child.spacingBefore + child.spacingAfter;
return x + child.style.spacingBefore + child.style.spacingAfter;
});
// Sum up the childrens' dimensions (including spacing) in the stack direction.
@@ -185,15 +185,15 @@ static std::function<BOOL(const ASStackUnpositionedItem &)> isFlexibleInViolatio
if (std::fabs(violation) < kViolationEpsilon) {
return [](const ASStackUnpositionedItem &l) { return NO; };
} else if (violation > 0) {
return [](const ASStackUnpositionedItem &l) { return l.child.flexGrow; };
return [](const ASStackUnpositionedItem &l) { return l.child.style.flexGrow; };
} else {
return [](const ASStackUnpositionedItem &l) { return l.child.flexShrink; };
return [](const ASStackUnpositionedItem &l) { return l.child.style.flexShrink; };
}
}
ASDISPLAYNODE_INLINE BOOL isFlexibleInBothDirections(id<ASLayoutable> child)
{
return child.flexGrow && child.flexShrink;
return child.style.flexGrow && child.style.flexShrink;
}
/**
@@ -309,8 +309,8 @@ static std::vector<ASStackUnpositionedItem> layoutChildrenAlongUnconstrainedStac
child,
crossChildLayout(child,
style,
ASDimensionResolve(child.flexBasis, stackDimension(style.direction, size), 0),
ASDimensionResolve(child.flexBasis, stackDimension(style.direction, size), INFINITY),
ASDimensionResolve(child.style.flexBasis, stackDimension(style.direction, size), 0),
ASDimensionResolve(child.style.flexBasis, stackDimension(style.direction, size), INFINITY),
minCrossDimension,
maxCrossDimension,
size)

View File

@@ -90,7 +90,7 @@ static NSString *suffixForCenteringOptions(ASCenterLayoutSpecCenteringOptions ce
{
ASDisplayNode *backgroundNode = ASDisplayNodeWithBackgroundColor([UIColor redColor]);
ASDisplayNode *foregroundNode = ASDisplayNodeWithBackgroundColor([UIColor redColor], CGSizeMake(10, 10));
foregroundNode.flexGrow = YES;
foregroundNode.style.flexGrow = YES;
ASCenterLayoutSpec *layoutSpec =
[ASCenterLayoutSpec

View File

@@ -23,8 +23,8 @@
CGSize nodeSize = CGSizeMake(100, 100);
ASDisplayNode *displayNode = [[ASDisplayNode alloc] init];
displayNode.width = ASDimensionMake(100);
displayNode.height = ASDimensionMake(100);
displayNode.style.width = ASDimensionMake(100);
displayNode.style.height = ASDimensionMake(100);
// Use a button node in here as ASButtonNode uses layoutSpecThatFits:
ASButtonNode *buttonNode = [ASButtonNode new];
@@ -80,7 +80,7 @@
CGSize nodeSize = CGSizeMake(100, 100);
ASDisplayNode *displayNode = [ASDisplayNode new];
[displayNode setSizeWithCGSize:nodeSize];
[displayNode.style setSizeWithCGSize:nodeSize];
ASButtonNode *buttonNode = [ASButtonNode new];
[displayNode addSubnode:buttonNode];

View File

@@ -44,11 +44,11 @@
imageNode.image = [self testImage];
// Snapshot testing requires that node is formally laid out.
[imageNode setSizeWithCGSize:forcedImageSize];
[imageNode.style setSizeWithCGSize:forcedImageSize];
[imageNode layoutThatFits:ASSizeRangeMake(CGSizeZero, forcedImageSize)];
ASSnapshotVerifyNode(imageNode, @"first");
[imageNode setSizeWithCGSize:CGSizeMake(200, 200)];
[imageNode.style setSizeWithCGSize:CGSizeMake(200, 200)];
[imageNode layoutThatFits:ASSizeRangeMake(CGSizeZero, CGSizeMake(200, 200))];
ASSnapshotVerifyNode(imageNode, @"second");

View File

@@ -35,8 +35,8 @@ __attribute__((overloadable)) static inline ASDisplayNode *ASDisplayNodeWithBack
ASDisplayNode *node = [[ASDisplayNode alloc] init];
node.layerBacked = YES;
node.backgroundColor = backgroundColor;
node.width = ASDimensionMakeWithPoints(size.width);
node.height = ASDimensionMakeWithPoints(size.height);
node.style.width = ASDimensionMakeWithPoints(size.width);
node.style.height = ASDimensionMakeWithPoints(size.height);
return node;
}

View File

@@ -107,7 +107,7 @@ static NSString *suffixForPositionOptions(ASRelativeLayoutSpecPosition horizonta
{
ASDisplayNode *backgroundNode = ASDisplayNodeWithBackgroundColor([UIColor redColor]);
ASDisplayNode *foregroundNode = ASDisplayNodeWithBackgroundColor([UIColor redColor], CGSizeMake(10, 10));
foregroundNode.flexGrow = YES;
foregroundNode.style.flexGrow = YES;
ASLayoutSpec *childSpec =
[ASBackgroundLayoutSpec

View File

@@ -36,27 +36,27 @@ static NSArray<ASDisplayNode *> *defaultSubnodesWithSameSize(CGSize subnodeSize,
ASDisplayNodeWithBackgroundColor([UIColor greenColor], subnodeSize)
];
for (ASDisplayNode *subnode in subnodes) {
subnode.flexGrow = flex;
subnode.flexShrink = flex;
subnode.style.flexGrow = flex;
subnode.style.flexShrink = flex;
}
return subnodes;
}
static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
{
node.width = ASDimensionMakeWithPoints(size.width);
node.height = ASDimensionMakeWithPoints(size.height);
node.style.width = ASDimensionMakeWithPoints(size.width);
node.style.height = ASDimensionMakeWithPoints(size.height);
}
- (void)testDefaultStackLayoutableFlexProperties
{
ASDisplayNode *displayNode = [[ASDisplayNode alloc] init];
XCTAssertEqual(displayNode.flexShrink, NO);
XCTAssertEqual(displayNode.flexGrow, NO);
XCTAssertEqual(displayNode.style.flexShrink, NO);
XCTAssertEqual(displayNode.style.flexGrow, NO);
const ASDimension unconstrainedDimension = ASDimensionAuto;
const ASDimension flexBasis = displayNode.flexBasis;
const ASDimension flexBasis = displayNode.style.flexBasis;
XCTAssertEqual(flexBasis.unit, unconstrainedDimension.unit);
XCTAssertEqual(flexBasis.value, unconstrainedDimension.value);
}
@@ -166,7 +166,7 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
ASStackLayoutSpecStyle style = {.direction = ASStackLayoutDirectionHorizontal};
NSArray<ASDisplayNode *> *subnodes = defaultSubnodesWithSameSize({50, 50}, NO);
subnodes[1].flexShrink = YES;
subnodes[1].style.flexShrink = YES;
// Width is 75px--that's less than the sum of the widths of the children, which is 100px.
static ASSizeRange kSize = {{75, 0}, {75, 150}};
@@ -260,23 +260,23 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
setCGSizeToNode({100, 70}, subnodes[1]);
setCGSizeToNode({150, 90}, subnodes[2]);
subnodes[1].spacingBefore = 10;
subnodes[2].spacingBefore = 20;
subnodes[1].style.spacingBefore = 10;
subnodes[2].style.spacingBefore = 20;
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingBefore"];
// Reset above spacing values
subnodes[1].spacingBefore = 0;
subnodes[2].spacingBefore = 0;
subnodes[1].style.spacingBefore = 0;
subnodes[2].style.spacingBefore = 0;
subnodes[1].spacingAfter = 10;
subnodes[2].spacingAfter = 20;
subnodes[1].style.spacingAfter = 10;
subnodes[2].style.spacingAfter = 20;
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingAfter"];
// Reset above spacing values
subnodes[1].spacingAfter = 0;
subnodes[2].spacingAfter = 0;
subnodes[1].style.spacingAfter = 0;
subnodes[2].style.spacingAfter = 0;
style.spacing = 10;
subnodes[1].spacingBefore = -10;
subnodes[1].spacingAfter = -10;
subnodes[1].style.spacingBefore = -10;
subnodes[1].style.spacingAfter = -10;
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingBalancedOut"];
}
@@ -292,9 +292,9 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
setCGSizeToNode({100, 70}, subnodes[1]);
setCGSizeToNode({150, 90}, subnodes[2]);
subnodes[0].spacingBefore = 0;
subnodes[1].spacingBefore = 20;
subnodes[2].spacingBefore = 30;
subnodes[0].style.spacingBefore = 0;
subnodes[1].style.spacingBefore = 20;
subnodes[2].style.spacingBefore = 30;
// width 0-300px; height 300px
static ASSizeRange kVariableHeight = {{0, 300}, {300, 300}};
@@ -351,9 +351,9 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
ASDisplayNode * subnode2 = ASDisplayNodeWithBackgroundColor([UIColor redColor], {50, 50});
ASRatioLayoutSpec *child1 = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.5 child:subnode1];
child1.flexBasis = ASDimensionMakeWithFraction(1);
child1.flexGrow = YES;
child1.flexShrink = YES;
child1.style.flexBasis = ASDimensionMakeWithFraction(1);
child1.style.flexGrow = YES;
child1.style.flexShrink = YES;
static ASSizeRange kFixedWidth = {{150, 0}, {150, INFINITY}};
[self testStackLayoutSpecWithStyle:style children:@[child1, subnode2] sizeRange:kFixedWidth subnodes:@[subnode1, subnode2] identifier:nil];
@@ -367,10 +367,10 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
};
ASDisplayNode *subnode1 = ASDisplayNodeWithBackgroundColor([UIColor redColor], {100, 100});
subnode1.flexShrink = YES;
subnode1.style.flexShrink = YES;
ASDisplayNode *subnode2 = ASDisplayNodeWithBackgroundColor([UIColor blueColor], {50, 50});
subnode2.flexShrink = YES;
subnode2.style.flexShrink = YES;
NSArray<ASDisplayNode *> *subnodes = @[subnode1, subnode2];
static ASSizeRange kFixedWidth = {{150, 0}, {150, 100}};
@@ -384,7 +384,7 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
ASDisplayNode *subnode1 = ASDisplayNodeWithBackgroundColor([UIColor redColor], {100, 100});
ASDisplayNode *subnode2 = ASDisplayNodeWithBackgroundColor([UIColor blueColor], {50, 50});
subnode2.alignSelf = ASStackLayoutAlignSelfCenter;
subnode2.style.alignSelf = ASStackLayoutAlignSelfCenter;
NSArray<ASDisplayNode *> *subnodes = @[subnode1, subnode2];
static ASSizeRange kFixedWidth = {{150, 0}, {150, INFINITY}};
@@ -404,9 +404,9 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
setCGSizeToNode({100, 70}, subnodes[1]);
setCGSizeToNode({150, 90}, subnodes[2]);
subnodes[0].spacingBefore = 0;
subnodes[1].spacingBefore = 20;
subnodes[2].spacingBefore = 30;
subnodes[0].style.spacingBefore = 0;
subnodes[1].style.spacingBefore = 20;
subnodes[2].style.spacingBefore = 30;
static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
@@ -425,9 +425,9 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
setCGSizeToNode({100, 70}, subnodes[1]);
setCGSizeToNode({150, 90}, subnodes[2]);
subnodes[0].spacingBefore = 0;
subnodes[1].spacingBefore = 20;
subnodes[2].spacingBefore = 30;
subnodes[0].style.spacingBefore = 0;
subnodes[1].style.spacingBefore = 20;
subnodes[2].style.spacingBefore = 30;
static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
@@ -446,9 +446,9 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
setCGSizeToNode({100, 70}, subnodes[1]);
setCGSizeToNode({150, 90}, subnodes[2]);
subnodes[0].spacingBefore = 0;
subnodes[1].spacingBefore = 20;
subnodes[2].spacingBefore = 30;
subnodes[0].style.spacingBefore = 0;
subnodes[1].style.spacingBefore = 20;
subnodes[2].style.spacingBefore = 30;
static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
@@ -467,9 +467,9 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
setCGSizeToNode({100, 70}, subnodes[1]);
setCGSizeToNode({150, 90}, subnodes[2]);
subnodes[0].spacingBefore = 0;
subnodes[1].spacingBefore = 20;
subnodes[2].spacingBefore = 30;
subnodes[0].style.spacingBefore = 0;
subnodes[1].style.spacingBefore = 20;
subnodes[2].style.spacingBefore = 30;
static ASSizeRange kVariableSize = {{200, 200}, {300, 300}};
// all children should be 200px wide
@@ -489,9 +489,9 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
setCGSizeToNode({100, 70}, subnodes[1]);
setCGSizeToNode({150, 90}, subnodes[2]);
subnodes[0].spacingBefore = 0;
subnodes[1].spacingBefore = 20;
subnodes[2].spacingBefore = 30;
subnodes[0].style.spacingBefore = 0;
subnodes[1].style.spacingBefore = 20;
subnodes[2].style.spacingBefore = 30;
static ASSizeRange kVariableSize = {{50, 50}, {300, 300}};
// all children should be 150px wide
@@ -512,8 +512,8 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
setCGSizeToNode({150, 150}, subnodes[1]);
for (ASDisplayNode *subnode in subnodes) {
subnode.flexGrow = YES;
subnode.flexBasis = ASDimensionMakeWithPoints(10);
subnode.style.flexGrow = YES;
subnode.style.flexBasis = ASDimensionMakeWithPoints(10);
}
// width 300px; height 0-150px.
@@ -531,12 +531,12 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
NSArray<ASDisplayNode *> *subnodes = defaultSubnodesWithSameSize({50, 50}, NO);
for (ASDisplayNode *subnode in subnodes) {
subnode.flexGrow = YES;
subnode.style.flexGrow = YES;
}
// This should override the intrinsic size of 50pts and instead compute to 50% = 100pts.
// The result should be that the red box is twice as wide as the blue and gree boxes after flexing.
subnodes[0].flexBasis = ASDimensionMakeWithFraction(0.5);
subnodes[0].style.flexBasis = ASDimensionMakeWithFraction(0.5);
static ASSizeRange kSize = {{200, 0}, {200, INFINITY}};
[self testStackLayoutSpecWithStyle:style sizeRange:kSize subnodes:subnodes identifier:nil];
@@ -552,7 +552,7 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
setCGSizeToNode({150, 50}, subnodes[2]);
for (ASDisplayNode *subnode in subnodes) {
subnode.flexBasis = ASDimensionMakeWithPoints(20);
subnode.style.flexBasis = ASDimensionMakeWithPoints(20);
}
static ASSizeRange kSize = {{300, 0}, {300, 150}};
@@ -568,8 +568,8 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
];
ASRatioLayoutSpec *child2 = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.0 child:subnodes[2]];
child2.flexGrow = YES;
child2.flexShrink = YES;
child2.style.flexGrow = YES;
child2.style.flexShrink = YES;
// If cross axis stretching occurred *before* flexing, then the blue child would be stretched to 3000 points tall.
// Instead it should be stretched to 300 points tall, matching the red child and not overlapping the green inset.
@@ -602,9 +602,9 @@ static void setCGSizeToNode(CGSize size, ASDisplayNode *node)
setCGSizeToNode({100, 50}, subnodes[1]);
setCGSizeToNode({200, 50}, subnodes[2]);
subnodes[0].flexShrink = YES;
subnodes[1].flexShrink = NO;
subnodes[2].flexShrink = YES;
subnodes[0].style.flexShrink = YES;
subnodes[1].style.flexShrink = NO;
subnodes[2].style.flexShrink = YES;
// A width of 400px results in a violation of 200px. This is distributed equally among each flexible child,
// causing both of them to be shrunk by 100px, resulting in widths of 300px, 100px, and 50px.

View File

@@ -34,10 +34,10 @@
- (void)testChildrenMeasuredWithAutoMaxSize
{
ASDisplayNode *firstChild = ASDisplayNodeWithBackgroundColor([UIColor redColor], (CGSize){50, 50});
firstChild.layoutPosition = CGPointMake(0, 0);
firstChild.style.layoutPosition = CGPointMake(0, 0);
ASDisplayNode *secondChild = ASDisplayNodeWithBackgroundColor([UIColor blueColor], (CGSize){100, 100});
secondChild.layoutPosition = CGPointMake(10, 60);
secondChild.style.layoutPosition = CGPointMake(10, 60);
ASSizeRange sizeRange = ASSizeRangeMake(CGSizeMake(10, 10), CGSizeMake(110, 160));
[self testWithChildren:@[firstChild, secondChild] sizeRange:sizeRange identifier:nil];
@@ -46,10 +46,10 @@
- (void)testWithSizeRange:(ASSizeRange)sizeRange identifier:(NSString *)identifier
{
ASDisplayNode *firstChild = ASDisplayNodeWithBackgroundColor([UIColor redColor], (CGSize){50, 50});
firstChild.layoutPosition = CGPointMake(0, 0);
firstChild.style.layoutPosition = CGPointMake(0, 0);
ASDisplayNode *secondChild = ASDisplayNodeWithBackgroundColor([UIColor blueColor], (CGSize){100, 100});
secondChild.layoutPosition = CGPointMake(0, 50);
secondChild.style.layoutPosition = CGPointMake(0, 50);
[self testWithChildren:@[firstChild, secondChild] sizeRange:sizeRange identifier:identifier];
}

View File

@@ -113,11 +113,11 @@
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
// username / photo location header vertical stack
_photoLocationLabel.flexShrink = YES;
_userNameLabel.flexShrink = YES;
_photoLocationLabel.style.flexShrink = YES;
_userNameLabel.style.flexShrink = YES;
ASStackLayoutSpec *headerSubStack = [ASStackLayoutSpec verticalStackLayoutSpec];
headerSubStack.flexShrink = YES;
headerSubStack.style.flexShrink = YES;
if (_photoLocationLabel.attributedText) {
[headerSubStack setChildren:@[_userNameLabel, _photoLocationLabel]];
} else {
@@ -127,12 +127,12 @@
// header stack
// constrain avatar image frame size
_userAvatarImageView.width = ASDimensionMakeWithPoints(USER_IMAGE_HEIGHT);
_userAvatarImageView.height = ASDimensionMakeWithPoints(USER_IMAGE_HEIGHT);
_photoTimeIntervalSincePostLabel.spacingBefore = HORIZONTAL_BUFFER; // to remove double spaces around spacer
_userAvatarImageView.style.width = ASDimensionMakeWithPoints(USER_IMAGE_HEIGHT);
_userAvatarImageView.style.height = ASDimensionMakeWithPoints(USER_IMAGE_HEIGHT);
_photoTimeIntervalSincePostLabel.style.spacingBefore = HORIZONTAL_BUFFER; // to remove double spaces around spacer
ASLayoutSpec *spacer = [[ASLayoutSpec alloc] init]; // FIXME: long locations overflow post time - set max size?
spacer.flexGrow = YES;
spacer.style.flexGrow = YES;
UIEdgeInsets avatarInsets = UIEdgeInsetsMake(HORIZONTAL_BUFFER, 0, HORIZONTAL_BUFFER, HORIZONTAL_BUFFER);
ASInsetLayoutSpec *avatarInset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:avatarInsets child:_userAvatarImageView];
@@ -159,8 +159,8 @@
CGFloat cellWidth = constrainedSize.max.width;
// constrain photo frame size
_photoImageView.width = ASDimensionMakeWithPoints(cellWidth);
_photoImageView.height = ASDimensionMakeWithPoints(cellWidth);
_photoImageView.style.width = ASDimensionMakeWithPoints(cellWidth);
_photoImageView.style.height = ASDimensionMakeWithPoints(cellWidth);
ASStackLayoutSpec *verticalStack = [ASStackLayoutSpec verticalStackLayoutSpec];
verticalStack.alignItems = ASStackLayoutAlignItemsStretch; // stretch headerStack to fill horizontal space