mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Addressed comments to LayoutOptions PR
This commit is contained in:
@@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
@implementation ASDisplayNode
|
@implementation ASDisplayNode
|
||||||
|
|
||||||
|
// these dynamic properties all defined in ASLayoutOptionsPrivate.m
|
||||||
@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender, sizeRange, layoutPosition, layoutOptions;
|
@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender, sizeRange, layoutPosition, layoutOptions;
|
||||||
@synthesize preferredFrameSize = _preferredFrameSize;
|
@synthesize preferredFrameSize = _preferredFrameSize;
|
||||||
@synthesize isFinalLayoutable = _isFinalLayoutable;
|
@synthesize isFinalLayoutable = _isFinalLayoutable;
|
||||||
|
|||||||
@@ -68,4 +68,15 @@ static NSString * const kBackgroundChildKey = @"kBackgroundChildKey";
|
|||||||
return [super childForIdentifier:kBackgroundChildKey];
|
return [super childForIdentifier:kBackgroundChildKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setChildren:(NSArray *)children
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert(NO, @"not supported by this layout spec");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *)children
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert(NO, @"not supported by this layout spec");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -90,4 +90,15 @@
|
|||||||
return [ASLayout layoutWithLayoutableObject:self size:size sublayouts:@[sublayout]];
|
return [ASLayout layoutWithLayoutableObject:self size:size sublayouts:@[sublayout]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setChildren:(NSArray *)children
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert(NO, @"not supported by this layout spec");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *)children
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert(NO, @"not supported by this layout spec");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -109,4 +109,15 @@ static CGFloat centerInset(CGFloat outer, CGFloat inner)
|
|||||||
return [ASLayout layoutWithLayoutableObject:self size:computedSize sublayouts:@[sublayout]];
|
return [ASLayout layoutWithLayoutableObject:self size:computedSize sublayouts:@[sublayout]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setChildren:(NSArray *)children
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert(NO, @"not supported by this layout spec");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *)children
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert(NO, @"not supported by this layout spec");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -12,8 +12,7 @@
|
|||||||
|
|
||||||
@protocol ASLayoutable;
|
@protocol ASLayoutable;
|
||||||
|
|
||||||
#import <AsyncDisplayKit/ASStackLayoutable.h>
|
#import <AsyncDisplayKit/ASLayoutSpec.h>
|
||||||
#import <AsyncDisplayKit/ASStaticLayoutable.h>
|
|
||||||
|
|
||||||
@interface ASLayoutOptions : NSObject <ASStackLayoutable, ASStaticLayoutable, NSCopying>
|
@interface ASLayoutOptions : NSObject <ASStackLayoutable, ASStaticLayoutable, NSCopying>
|
||||||
|
|
||||||
@@ -24,8 +23,7 @@
|
|||||||
- (void)setValuesFromLayoutable:(id<ASLayoutable>)layoutable;
|
- (void)setValuesFromLayoutable:(id<ASLayoutable>)layoutable;
|
||||||
|
|
||||||
#pragma mark - Subclasses should implement these!
|
#pragma mark - Subclasses should implement these!
|
||||||
- (void)setupDefaults;
|
- (void)propogateOptionsFromLayoutOptions:(ASLayoutOptions *)layoutOptions;
|
||||||
- (void)copyIntoOptions:(ASLayoutOptions *)layoutOptions;
|
|
||||||
|
|
||||||
#pragma mark - ASStackLayoutable
|
#pragma mark - ASStackLayoutable
|
||||||
|
|
||||||
@@ -43,5 +41,4 @@
|
|||||||
@property (nonatomic, readwrite) ASRelativeSizeRange sizeRange;
|
@property (nonatomic, readwrite) ASRelativeSizeRange sizeRange;
|
||||||
@property (nonatomic, readwrite) CGPoint layoutPosition;
|
@property (nonatomic, readwrite) CGPoint layoutPosition;
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -63,7 +63,20 @@ static Class gDefaultLayoutOptionsClass = nil;
|
|||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self) {
|
if (self) {
|
||||||
[self setupDefaults];
|
|
||||||
|
self.flexBasis = ASRelativeDimensionUnconstrained;
|
||||||
|
self.sizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(CGSizeZero), ASRelativeSizeMakeWithCGSize(CGSizeZero));
|
||||||
|
self.layoutPosition = CGPointZero;
|
||||||
|
|
||||||
|
// The following properties use a default value of 0 which we do not need to assign.
|
||||||
|
// self.spacingBefore = 0;
|
||||||
|
// self.spacingAfter = 0;
|
||||||
|
// self.flexGrow = NO;
|
||||||
|
// self.flexShrink = NO;
|
||||||
|
// self.alignSelf = ASStackLayoutAlignSelfAuto;
|
||||||
|
// self.ascender = 0;
|
||||||
|
// self.descender = 0;
|
||||||
|
|
||||||
[self setValuesFromLayoutable:layoutable];
|
[self setValuesFromLayoutable:layoutable];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
@@ -73,59 +86,57 @@ static Class gDefaultLayoutOptionsClass = nil;
|
|||||||
- (id)copyWithZone:(NSZone *)zone
|
- (id)copyWithZone:(NSZone *)zone
|
||||||
{
|
{
|
||||||
ASLayoutOptions *copy = [[[self class] alloc] init];
|
ASLayoutOptions *copy = [[[self class] alloc] init];
|
||||||
[self copyIntoOptions:copy];
|
[copy propogateOptionsFromLayoutOptions:self];
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)copyIntoOptions:(ASLayoutOptions *)copy
|
- (void)propogateOptionsFromLayoutOptions:(ASLayoutOptions *)layoutOptions
|
||||||
{
|
{
|
||||||
ASDN::MutexLocker l(_propertyLock);
|
ASDN::MutexLocker l(_propertyLock);
|
||||||
copy.flexBasis = self.flexBasis;
|
self.flexBasis = layoutOptions.flexBasis;
|
||||||
copy.spacingAfter = self.spacingAfter;
|
self.spacingAfter = layoutOptions.spacingAfter;
|
||||||
copy.spacingBefore = self.spacingBefore;
|
self.spacingBefore = layoutOptions.spacingBefore;
|
||||||
copy.flexGrow = self.flexGrow;
|
self.flexGrow = layoutOptions.flexGrow;
|
||||||
copy.flexShrink = self.flexShrink;
|
self.flexShrink = layoutOptions.flexShrink;
|
||||||
|
|
||||||
copy.ascender = self.ascender;
|
self.ascender = layoutOptions.ascender;
|
||||||
copy.descender = self.descender;
|
self.descender = layoutOptions.descender;
|
||||||
|
|
||||||
copy.sizeRange = self.sizeRange;
|
self.sizeRange = layoutOptions.sizeRange;
|
||||||
copy.layoutPosition = self.layoutPosition;
|
self.layoutPosition = layoutOptions.layoutPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
#pragma mark - Defaults
|
* Given an id<ASLayoutable>, set up layout options that are intrinsically defined by the layoutable.
|
||||||
- (void)setupDefaults
|
*
|
||||||
{
|
* While this could be done in the layoutable object itself, moving the logic into the ASLayoutOptions class
|
||||||
self.flexBasis = ASRelativeDimensionUnconstrained;
|
* allows a custom spec to set up defaults without needing to alter the layoutable itself. For example,
|
||||||
self.spacingBefore = 0;
|
* image you were creating a custom baseline spec that needed ascender/descender. To assign values automatically
|
||||||
self.spacingAfter = 0;
|
* when a text node's attribute string is set, you would need to subclass ASTextNode and assign the values in the
|
||||||
self.flexGrow = NO;
|
* override of setAttributeString. However, assigning the defaults in an ASLayoutOptions subclass's
|
||||||
self.flexShrink = NO;
|
* setValuesFromLayoutable allows you to create a custom spec without the need to create a
|
||||||
self.alignSelf = ASStackLayoutAlignSelfAuto;
|
* subclass of ASTextNode.
|
||||||
|
*
|
||||||
self.ascender = 0;
|
* @param layoutable The layoutable object to inspect for default intrinsic layout option values
|
||||||
self.descender = 0;
|
*/
|
||||||
|
|
||||||
self.sizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(CGSizeZero), ASRelativeSizeMakeWithCGSize(CGSizeZero));
|
|
||||||
self.layoutPosition = CGPointZero;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do this here instead of in Node/Spec subclasses so that custom specs can set default values
|
|
||||||
- (void)setValuesFromLayoutable:(id<ASLayoutable>)layoutable
|
- (void)setValuesFromLayoutable:(id<ASLayoutable>)layoutable
|
||||||
{
|
{
|
||||||
ASDN::MutexLocker l(_propertyLock);
|
ASDN::MutexLocker l(_propertyLock);
|
||||||
if ([layoutable isKindOfClass:[ASTextNode class]]) {
|
|
||||||
ASTextNode *textNode = (ASTextNode *)layoutable;
|
|
||||||
if (textNode.attributedString.length > 0) {
|
|
||||||
self.ascender = round([[textNode.attributedString attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender] * ASScreenScale())/ASScreenScale();
|
|
||||||
self.descender = round([[textNode.attributedString attribute:NSFontAttributeName atIndex:textNode.attributedString.length - 1 effectiveRange:NULL] descender] * ASScreenScale())/ASScreenScale();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ([layoutable isKindOfClass:[ASDisplayNode class]]) {
|
if ([layoutable isKindOfClass:[ASDisplayNode class]]) {
|
||||||
ASDisplayNode *displayNode = (ASDisplayNode *)layoutable;
|
ASDisplayNode *displayNode = (ASDisplayNode *)layoutable;
|
||||||
self.sizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(displayNode.preferredFrameSize), ASRelativeSizeMakeWithCGSize(displayNode.preferredFrameSize));
|
self.sizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(displayNode.preferredFrameSize), ASRelativeSizeMakeWithCGSize(displayNode.preferredFrameSize));
|
||||||
self.layoutPosition = displayNode.frame.origin;
|
self.layoutPosition = displayNode.frame.origin;
|
||||||
|
|
||||||
|
if ([layoutable isKindOfClass:[ASTextNode class]]) {
|
||||||
|
ASTextNode *textNode = (ASTextNode *)layoutable;
|
||||||
|
NSAttributedString *attributedString = textNode.attributedString;
|
||||||
|
if (attributedString.length > 0) {
|
||||||
|
CGFloat screenScale = ASScreenScale();
|
||||||
|
self.ascender = round([[attributedString attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender] * screenScale)/screenScale;
|
||||||
|
self.descender = round([[attributedString attribute:NSFontAttributeName atIndex:attributedString.length - 1 effectiveRange:NULL] descender] * screenScale)/screenScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,25 +10,24 @@
|
|||||||
|
|
||||||
#import <AsyncDisplayKit/ASDisplayNode.h>
|
#import <AsyncDisplayKit/ASDisplayNode.h>
|
||||||
#import <AsyncDisplayKit/ASLayoutSpec.h>
|
#import <AsyncDisplayKit/ASLayoutSpec.h>
|
||||||
|
#import <AsyncDisplayKit/ASThread.h>
|
||||||
|
|
||||||
@interface ASDisplayNode()
|
|
||||||
{
|
|
||||||
ASLayoutOptions *_layoutOptions;
|
|
||||||
dispatch_once_t _layoutOptionsInitializeToken;
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface ASDisplayNode(ASLayoutOptions)<ASLayoutable>
|
@interface ASDisplayNode(ASLayoutOptions)<ASLayoutable>
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface ASLayoutSpec()
|
@interface ASDisplayNode()
|
||||||
{
|
{
|
||||||
ASLayoutOptions *_layoutOptions;
|
ASLayoutOptions *_layoutOptions;
|
||||||
dispatch_once_t _layoutOptionsInitializeToken;
|
ASDN::RecursiveMutex _layoutOptionsLock;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface ASLayoutSpec(ASLayoutOptions)<ASLayoutable>
|
@interface ASLayoutSpec(ASLayoutOptions)<ASLayoutable>
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@interface ASLayoutSpec()
|
||||||
|
{
|
||||||
|
ASLayoutOptions *_layoutOptions;
|
||||||
|
ASDN::RecursiveMutex _layoutOptionsLock;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|||||||
@@ -10,16 +10,27 @@
|
|||||||
|
|
||||||
#import "ASLayoutOptionsPrivate.h"
|
#import "ASLayoutOptionsPrivate.h"
|
||||||
#import <AsyncDisplayKit/ASDisplayNodeInternal.h>
|
#import <AsyncDisplayKit/ASDisplayNodeInternal.h>
|
||||||
|
#import "ASThread.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Both an ASDisplayNode and an ASLayoutSpec conform to ASLayoutable. There are several properties
|
||||||
|
* in ASLayoutable that are used as layoutOptions 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
|
||||||
|
* ASLayoutOptions class. 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.
|
||||||
|
*/
|
||||||
#define ASLayoutOptionsForwarding \
|
#define ASLayoutOptionsForwarding \
|
||||||
- (ASLayoutOptions *)layoutOptions\
|
- (ASLayoutOptions *)layoutOptions\
|
||||||
{\
|
{\
|
||||||
dispatch_once(&_layoutOptionsInitializeToken, ^{\
|
ASDN::MutexLocker l(_layoutOptionsLock);\
|
||||||
if (_layoutOptions == nil) {\
|
if (_layoutOptions == nil) {\
|
||||||
_layoutOptions = [[[ASLayoutOptions defaultLayoutOptionsClass] alloc] initWithLayoutable:self];\
|
_layoutOptions = [[[ASLayoutOptions defaultLayoutOptionsClass] alloc] initWithLayoutable:self];\
|
||||||
}\
|
}\
|
||||||
});\
|
|
||||||
return _layoutOptions;\
|
return _layoutOptions;\
|
||||||
}\
|
}\
|
||||||
\
|
\
|
||||||
|
|||||||
@@ -22,10 +22,37 @@
|
|||||||
|
|
||||||
- (instancetype)init;
|
- (instancetype)init;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set child methods
|
||||||
|
*
|
||||||
|
* Every ASLayoutSpec must act on at least one child. The ASLayoutSpec base class takes the
|
||||||
|
* reponsibility of holding on to the spec children. For a layout spec like ASInsetLayoutSpec that
|
||||||
|
* only requires a single child, the child can be added by calling setChild:.
|
||||||
|
*
|
||||||
|
* For layout specs that require a known number of children (ASBackgroundLayoutSpec, for example)
|
||||||
|
* a subclass should use the setChild to set the "primary" child. It can then use setChild:forIdentifier:
|
||||||
|
* to set any other required children. Ideally a subclass would hide this from the user, and use the
|
||||||
|
* setChildWithIdentifier: internally. For example, ASBackgroundLayoutSpec exposes a backgroundChild
|
||||||
|
* property that behind the scenes is calling setChild:forIdentifier:.
|
||||||
|
*
|
||||||
|
* Finally, a layout spec like ASStackLayoutSpec can take an unknown number of children. In this case,
|
||||||
|
* the setChildren: method should be used. For good measure, in these layout specs it probably makes
|
||||||
|
* sense to define setChild: to do something appropriate or to assert.
|
||||||
|
*/
|
||||||
- (void)setChild:(id<ASLayoutable>)child;
|
- (void)setChild:(id<ASLayoutable>)child;
|
||||||
- (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier;
|
- (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier;
|
||||||
- (void)setChildren:(NSArray *)children;
|
- (void)setChildren:(NSArray *)children;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get child methods
|
||||||
|
*
|
||||||
|
* There is a corresponding "getChild" method for the above "setChild" methods. If a subclass
|
||||||
|
* has extra layoutable children, it is recommended to make a corresponding get method for that
|
||||||
|
* child. For example, the ASBackgroundLayoutSpec responds to backgroundChild.
|
||||||
|
*
|
||||||
|
* If a get method is called on a spec that doesn't make sense, then the standard is to assert.
|
||||||
|
* For example, calling children on an ASInsetLayoutSpec will assert.
|
||||||
|
*/
|
||||||
- (id<ASLayoutable>)child;
|
- (id<ASLayoutable>)child;
|
||||||
- (id<ASLayoutable>)childForIdentifier:(NSString *)identifier;
|
- (id<ASLayoutable>)childForIdentifier:(NSString *)identifier;
|
||||||
- (NSArray *)children;
|
- (NSArray *)children;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#import "ASLayout.h"
|
#import "ASLayout.h"
|
||||||
#import "ASLayoutOptions.h"
|
#import "ASLayoutOptions.h"
|
||||||
#import "ASLayoutOptionsPrivate.h"
|
#import "ASLayoutOptionsPrivate.h"
|
||||||
|
#import "ASThread.h"
|
||||||
|
|
||||||
#import <objc/runtime.h>
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey";
|
|||||||
|
|
||||||
@implementation ASLayoutSpec
|
@implementation ASLayoutSpec
|
||||||
|
|
||||||
|
// these dynamic properties all defined in ASLayoutOptionsPrivate.m
|
||||||
@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender, sizeRange, layoutPosition, layoutOptions;
|
@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender, sizeRange, layoutPosition, layoutOptions;
|
||||||
@synthesize layoutChildren = _layoutChildren;
|
@synthesize layoutChildren = _layoutChildren;
|
||||||
@synthesize isFinalLayoutable = _isFinalLayoutable;
|
@synthesize isFinalLayoutable = _isFinalLayoutable;
|
||||||
@@ -80,8 +82,7 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey";
|
|||||||
|
|
||||||
id<ASLayoutable> finalLayoutable = [child finalLayoutable];
|
id<ASLayoutable> finalLayoutable = [child finalLayoutable];
|
||||||
if (finalLayoutable != child) {
|
if (finalLayoutable != child) {
|
||||||
ASLayoutOptions *layoutOptions = [child layoutOptions];
|
[finalLayoutable.layoutOptions propogateOptionsFromLayoutOptions:child.layoutOptions];
|
||||||
[layoutOptions copyIntoOptions:finalLayoutable.layoutOptions];
|
|
||||||
return finalLayoutable;
|
return finalLayoutable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,22 @@
|
|||||||
@class ASLayoutSpec;
|
@class ASLayoutSpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ASLayoutable protocol declares a method for measuring the layout of an object. A class must implement the method
|
* The ASLayoutable protocol declares a method for measuring the layout of an object. A layout
|
||||||
* so that instances of that class can be used to build layout trees. The protocol also provides information
|
* is defined by an ASLayout return value, and must specify 1) the size (but not position) of the
|
||||||
* about how an object should be laid out within an ASStackLayoutSpec.
|
* layoutable object, and 2) the size and position of all of its immediate child objects. The tree
|
||||||
|
* recursion is driven by parents requesting layouts from their children in order to determine their
|
||||||
|
* size, followed by the parents setting the position of the children once the size is known
|
||||||
|
*
|
||||||
|
* The protocol also implements a "family" of Layoutable protocols. These protocols contain layout
|
||||||
|
* options that can be used for specific layout specs. For example, ASStackLayoutSpec has options
|
||||||
|
* defining how a layoutable should shrink or grow based upon available space.
|
||||||
|
*
|
||||||
|
* These layout options are all stored in an ASLayoutOptions class (that is defined in ASLayoutablePrivate).
|
||||||
|
* Generally you needn't worry about the layout options class, as the layoutable protocols allow all direct
|
||||||
|
* access to the options via convenience properties. If you are creating custom layout spec, then you can
|
||||||
|
* extend the backing layout options class to accomodate any new layout options.
|
||||||
*/
|
*/
|
||||||
@protocol ASLayoutable <ASLayoutablePrivate, ASStackLayoutable, ASStaticLayoutable>
|
@protocol ASLayoutable <ASStackLayoutable, ASStaticLayoutable, ASLayoutablePrivate>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract Calculate a layout based on given size range.
|
* @abstract Calculate a layout based on given size range.
|
||||||
@@ -35,4 +46,64 @@
|
|||||||
*/
|
*/
|
||||||
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize;
|
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize;
|
||||||
|
|
||||||
|
|
||||||
|
#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 ASRelativeDimensionUnconstrained.
|
||||||
|
* Used when attached to a stack layout.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readwrite) ASRelativeDimension 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
|
||||||
|
/**
|
||||||
|
If specified, the child's size is restricted according to this size. Percentages are resolved relative to the static layout spec.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) ASRelativeSizeRange sizeRange;
|
||||||
|
|
||||||
|
/** The position of this object within its parent spec. */
|
||||||
|
@property (nonatomic, assign) CGPoint layoutPosition;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -61,4 +61,15 @@ static NSString * const kOverlayChildKey = @"kOverlayChildKey";
|
|||||||
return [ASLayout layoutWithLayoutableObject:self size:contentsLayout.size sublayouts:sublayouts];
|
return [ASLayout layoutWithLayoutableObject:self size:contentsLayout.size sublayouts:sublayouts];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setChildren:(NSArray *)children
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert(NO, @"not supported by this layout spec");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *)children
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert(NO, @"not supported by this layout spec");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -75,4 +75,15 @@
|
|||||||
return [ASLayout layoutWithLayoutableObject:self size:sublayout.size sublayouts:@[sublayout]];
|
return [ASLayout layoutWithLayoutableObject:self size:sublayout.size sublayouts:@[sublayout]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setChildren:(NSArray *)children
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert(NO, @"not supported by this layout spec");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *)children
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert(NO, @"not supported by this layout spec");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -87,6 +87,12 @@
|
|||||||
ASDisplayNodeAssert(NO, @"ASStackLayoutSpec only supports setChildren");
|
ASDisplayNodeAssert(NO, @"ASStackLayoutSpec only supports setChildren");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id<ASLayoutable>)childForIdentifier:(NSString *)identifier
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert(NO, @"ASStackLayoutSpec only supports children");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
|
- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
|
||||||
{
|
{
|
||||||
ASStackLayoutSpecStyle style = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems, .baselineRelativeArrangement = _baselineRelativeArrangement};
|
ASStackLayoutSpecStyle style = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems, .baselineRelativeArrangement = _baselineRelativeArrangement};
|
||||||
|
|||||||
@@ -47,16 +47,15 @@
|
|||||||
|
|
||||||
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:self.children.count];
|
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:self.children.count];
|
||||||
for (id<ASLayoutable> child in self.children) {
|
for (id<ASLayoutable> child in self.children) {
|
||||||
ASLayoutOptions *layoutOptions = child.layoutOptions;
|
|
||||||
CGSize autoMaxSize = {
|
CGSize autoMaxSize = {
|
||||||
constrainedSize.max.width - layoutOptions.layoutPosition.x,
|
constrainedSize.max.width - child.layoutPosition.x,
|
||||||
constrainedSize.max.height - layoutOptions.layoutPosition.y
|
constrainedSize.max.height - child.layoutPosition.y
|
||||||
};
|
};
|
||||||
ASSizeRange childConstraint = ASRelativeSizeRangeEqualToRelativeSizeRange(ASRelativeSizeRangeUnconstrained, layoutOptions.sizeRange)
|
ASSizeRange childConstraint = ASRelativeSizeRangeEqualToRelativeSizeRange(ASRelativeSizeRangeUnconstrained, child.sizeRange)
|
||||||
? ASSizeRangeMake({0, 0}, autoMaxSize)
|
? ASSizeRangeMake({0, 0}, autoMaxSize)
|
||||||
: ASRelativeSizeRangeResolve(layoutOptions.sizeRange, size);
|
: ASRelativeSizeRangeResolve(child.sizeRange, size);
|
||||||
ASLayout *sublayout = [child measureWithSizeRange:childConstraint];
|
ASLayout *sublayout = [child measureWithSizeRange:childConstraint];
|
||||||
sublayout.position = layoutOptions.layoutPosition;
|
sublayout.position = child.layoutPosition;
|
||||||
[sublayouts addObject:sublayout];
|
[sublayouts addObject:sublayout];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,4 +78,15 @@
|
|||||||
sublayouts:sublayouts];
|
sublayouts:sublayouts];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setChild:(id<ASLayoutable>)child forIdentifier:(NSString *)identifier
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert(NO, @"ASStackLayoutSpec only supports setChildren");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id<ASLayoutable>)childForIdentifier:(NSString *)identifier
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssert(NO, @"ASStackLayoutSpec only supports children");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ static CGFloat baselineForItem(const ASStackLayoutSpecStyle &style,
|
|||||||
__weak id<ASLayoutable> child = layout.layoutableObject;
|
__weak id<ASLayoutable> child = layout.layoutableObject;
|
||||||
switch (style.alignItems) {
|
switch (style.alignItems) {
|
||||||
case ASStackLayoutAlignItemsBaselineFirst:
|
case ASStackLayoutAlignItemsBaselineFirst:
|
||||||
return child.layoutOptions.ascender;
|
return child.ascender;
|
||||||
case ASStackLayoutAlignItemsBaselineLast:
|
case ASStackLayoutAlignItemsBaselineLast:
|
||||||
return layout.size.height + child.layoutOptions.descender;
|
return layout.size.height + child.descender;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ static CGFloat baselineOffset(const ASStackLayoutSpecStyle &style,
|
|||||||
__weak id<ASLayoutable> child = l.layoutableObject;
|
__weak id<ASLayoutable> child = l.layoutableObject;
|
||||||
switch (style.alignItems) {
|
switch (style.alignItems) {
|
||||||
case ASStackLayoutAlignItemsBaselineFirst:
|
case ASStackLayoutAlignItemsBaselineFirst:
|
||||||
return maxAscender - child.layoutOptions.ascender;
|
return maxAscender - child.ascender;
|
||||||
case ASStackLayoutAlignItemsBaselineLast:
|
case ASStackLayoutAlignItemsBaselineLast:
|
||||||
return maxBaseline - baselineForItem(style, l);
|
return maxBaseline - baselineForItem(style, l);
|
||||||
|
|
||||||
@@ -91,9 +91,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.
|
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){
|
const auto ascenderIt = std::max_element(positionedLayout.sublayouts.begin(), positionedLayout.sublayouts.end(), [&](const ASLayout *a, const ASLayout *b){
|
||||||
return a.layoutableObject.layoutOptions.ascender < b.layoutableObject.layoutOptions.ascender;
|
return a.layoutableObject.ascender < b.layoutableObject.ascender;
|
||||||
});
|
});
|
||||||
const CGFloat maxAscender = baselineIt == positionedLayout.sublayouts.end() ? 0 : (*ascenderIt).layoutableObject.layoutOptions.ascender;
|
const CGFloat maxAscender = baselineIt == positionedLayout.sublayouts.end() ? 0 : (*ascenderIt).layoutableObject.ascender;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Step 3: Take each child and update its layout position based on the baseline offset.
|
Step 3: Take each child and update its layout position based on the baseline offset.
|
||||||
@@ -107,7 +107,7 @@ ASStackBaselinePositionedLayout ASStackBaselinePositionedLayout::compute(const A
|
|||||||
BOOL first = YES;
|
BOOL first = YES;
|
||||||
auto stackedChildren = AS::map(positionedLayout.sublayouts, [&](ASLayout *l) -> ASLayout *{
|
auto stackedChildren = AS::map(positionedLayout.sublayouts, [&](ASLayout *l) -> ASLayout *{
|
||||||
__weak id<ASLayoutable> child = l.layoutableObject;
|
__weak id<ASLayoutable> child = l.layoutableObject;
|
||||||
p = p + directionPoint(style.direction, child.layoutOptions.spacingBefore, 0);
|
p = p + directionPoint(style.direction, child.spacingBefore, 0);
|
||||||
if (first) {
|
if (first) {
|
||||||
// if this is the first item use the previously computed start point
|
// if this is the first item use the previously computed start point
|
||||||
p = l.position;
|
p = l.position;
|
||||||
@@ -124,9 +124,9 @@ ASStackBaselinePositionedLayout ASStackBaselinePositionedLayout::compute(const A
|
|||||||
// node from baselines and not bounding boxes.
|
// node from baselines and not bounding boxes.
|
||||||
CGFloat spacingAfterBaseline = 0;
|
CGFloat spacingAfterBaseline = 0;
|
||||||
if (style.direction == ASStackLayoutDirectionVertical) {
|
if (style.direction == ASStackLayoutDirectionVertical) {
|
||||||
spacingAfterBaseline = child.layoutOptions.descender;
|
spacingAfterBaseline = child.descender;
|
||||||
}
|
}
|
||||||
p = p + directionPoint(style.direction, stackDimension(style.direction, l.size) + child.layoutOptions.spacingAfter + spacingAfterBaseline, 0);
|
p = p + directionPoint(style.direction, stackDimension(style.direction, l.size) + child.spacingAfter + spacingAfterBaseline, 0);
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
});
|
});
|
||||||
@@ -156,7 +156,7 @@ ASStackBaselinePositionedLayout ASStackBaselinePositionedLayout::compute(const A
|
|||||||
const auto descenderIt = std::max_element(stackedChildren.begin(), stackedChildren.end(), [&](const ASLayout *a, const ASLayout *b){
|
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;
|
return a.position.y + a.size.height < b.position.y + b.size.height;
|
||||||
});
|
});
|
||||||
const CGFloat minDescender = descenderIt == stackedChildren.end() ? 0 : (*descenderIt).layoutableObject.layoutOptions.descender;
|
const CGFloat minDescender = descenderIt == stackedChildren.end() ? 0 : (*descenderIt).layoutableObject.descender;
|
||||||
|
|
||||||
return {stackedChildren, crossSize, maxAscender, minDescender};
|
return {stackedChildren, crossSize, maxAscender, minDescender};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ static CGFloat crossOffset(const ASStackLayoutSpecStyle &style,
|
|||||||
const ASStackUnpositionedItem &l,
|
const ASStackUnpositionedItem &l,
|
||||||
const CGFloat crossSize)
|
const CGFloat crossSize)
|
||||||
{
|
{
|
||||||
switch (alignment(l.child.layoutOptions.alignSelf, style.alignItems)) {
|
switch (alignment(l.child.alignSelf, style.alignItems)) {
|
||||||
case ASStackLayoutAlignItemsEnd:
|
case ASStackLayoutAlignItemsEnd:
|
||||||
return crossSize - crossDimension(style.direction, l.layout.size);
|
return crossSize - crossDimension(style.direction, l.layout.size);
|
||||||
case ASStackLayoutAlignItemsCenter:
|
case ASStackLayoutAlignItemsCenter:
|
||||||
@@ -51,14 +51,14 @@ static ASStackPositionedLayout stackedLayout(const ASStackLayoutSpecStyle &style
|
|||||||
CGPoint p = directionPoint(style.direction, offset, 0);
|
CGPoint p = directionPoint(style.direction, offset, 0);
|
||||||
BOOL first = YES;
|
BOOL first = YES;
|
||||||
auto stackedChildren = AS::map(unpositionedLayout.items, [&](const ASStackUnpositionedItem &l) -> ASLayout *{
|
auto stackedChildren = AS::map(unpositionedLayout.items, [&](const ASStackUnpositionedItem &l) -> ASLayout *{
|
||||||
p = p + directionPoint(style.direction, l.child.layoutOptions.spacingBefore, 0);
|
p = p + directionPoint(style.direction, l.child.spacingBefore, 0);
|
||||||
if (!first) {
|
if (!first) {
|
||||||
p = p + directionPoint(style.direction, style.spacing, 0);
|
p = p + directionPoint(style.direction, style.spacing, 0);
|
||||||
}
|
}
|
||||||
first = NO;
|
first = NO;
|
||||||
l.layout.position = p + directionPoint(style.direction, 0, crossOffset(style, l, crossSize));
|
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.layoutOptions.spacingAfter, 0);
|
p = p + directionPoint(style.direction, stackDimension(style.direction, l.layout.size) + l.child.spacingAfter, 0);
|
||||||
return l.layout;
|
return l.layout;
|
||||||
});
|
});
|
||||||
return {stackedChildren, crossSize};
|
return {stackedChildren, crossSize};
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ static ASLayout *crossChildLayout(const id<ASLayoutable> child,
|
|||||||
const CGFloat crossMin,
|
const CGFloat crossMin,
|
||||||
const CGFloat crossMax)
|
const CGFloat crossMax)
|
||||||
{
|
{
|
||||||
const ASStackLayoutAlignItems alignItems = alignment(child.layoutOptions.alignSelf, style.alignItems);
|
const ASStackLayoutAlignItems alignItems = alignment(child.alignSelf, style.alignItems);
|
||||||
// stretched children will have a cross dimension of at least crossMin
|
// stretched children will have a cross dimension of at least crossMin
|
||||||
const CGFloat childCrossMin = alignItems == ASStackLayoutAlignItemsStretch ? crossMin : 0;
|
const CGFloat childCrossMin = alignItems == ASStackLayoutAlignItemsStretch ? crossMin : 0;
|
||||||
const ASSizeRange childSizeRange = directionSizeRange(style.direction, stackMin, stackMax, childCrossMin, crossMax);
|
const ASSizeRange childSizeRange = directionSizeRange(style.direction, stackMin, stackMax, childCrossMin, crossMax);
|
||||||
@@ -76,7 +76,7 @@ static void stretchChildrenAlongCrossDimension(std::vector<ASStackUnpositionedIt
|
|||||||
|
|
||||||
const CGFloat childCrossMax = it == layouts.end() ? 0 : crossDimension(style.direction, it->layout.size);
|
const CGFloat childCrossMax = it == layouts.end() ? 0 : crossDimension(style.direction, it->layout.size);
|
||||||
for (auto &l : layouts) {
|
for (auto &l : layouts) {
|
||||||
const ASStackLayoutAlignItems alignItems = alignment(l.child.layoutOptions.alignSelf, style.alignItems);
|
const ASStackLayoutAlignItems alignItems = alignment(l.child.alignSelf, style.alignItems);
|
||||||
|
|
||||||
const CGFloat cross = crossDimension(style.direction, l.layout.size);
|
const CGFloat cross = crossDimension(style.direction, l.layout.size);
|
||||||
const CGFloat stack = stackDimension(style.direction, l.layout.size);
|
const CGFloat stack = stackDimension(style.direction, l.layout.size);
|
||||||
@@ -112,7 +112,7 @@ static CGFloat computeStackDimensionSum(const std::vector<ASStackUnpositionedIte
|
|||||||
// Start from default spacing between each child:
|
// Start from default spacing between each child:
|
||||||
children.empty() ? 0 : style.spacing * (children.size() - 1),
|
children.empty() ? 0 : style.spacing * (children.size() - 1),
|
||||||
[&](CGFloat x, const ASStackUnpositionedItem &l) {
|
[&](CGFloat x, const ASStackUnpositionedItem &l) {
|
||||||
return x + l.child.layoutOptions.spacingBefore + l.child.layoutOptions.spacingAfter;
|
return x + l.child.spacingBefore + l.child.spacingAfter;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sum up the childrens' dimensions (including spacing) in the stack direction.
|
// Sum up the childrens' dimensions (including spacing) in the stack direction.
|
||||||
@@ -181,15 +181,15 @@ static std::function<BOOL(const ASStackUnpositionedItem &)> isFlexibleInViolatio
|
|||||||
if (fabs(violation) < kViolationEpsilon) {
|
if (fabs(violation) < kViolationEpsilon) {
|
||||||
return [](const ASStackUnpositionedItem &l) { return NO; };
|
return [](const ASStackUnpositionedItem &l) { return NO; };
|
||||||
} else if (violation > 0) {
|
} else if (violation > 0) {
|
||||||
return [](const ASStackUnpositionedItem &l) { return l.child.layoutOptions.flexGrow; };
|
return [](const ASStackUnpositionedItem &l) { return l.child.flexGrow; };
|
||||||
} else {
|
} else {
|
||||||
return [](const ASStackUnpositionedItem &l) { return l.child.layoutOptions.flexShrink; };
|
return [](const ASStackUnpositionedItem &l) { return l.child.flexShrink; };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASDISPLAYNODE_INLINE BOOL isFlexibleInBothDirections(id<ASLayoutable> child)
|
ASDISPLAYNODE_INLINE BOOL isFlexibleInBothDirections(id<ASLayoutable> child)
|
||||||
{
|
{
|
||||||
return child.layoutOptions.flexGrow && child.layoutOptions.flexShrink;
|
return child.flexGrow && child.flexShrink;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -294,8 +294,8 @@ static std::vector<ASStackUnpositionedItem> layoutChildrenAlongUnconstrainedStac
|
|||||||
const CGFloat maxCrossDimension = crossDimension(style.direction, sizeRange.max);
|
const CGFloat maxCrossDimension = crossDimension(style.direction, sizeRange.max);
|
||||||
|
|
||||||
return AS::map(children, [&](id<ASLayoutable> child) -> ASStackUnpositionedItem {
|
return AS::map(children, [&](id<ASLayoutable> child) -> ASStackUnpositionedItem {
|
||||||
const BOOL isUnconstrainedFlexBasis = ASRelativeDimensionEqualToRelativeDimension(ASRelativeDimensionUnconstrained, child.layoutOptions.flexBasis);
|
const BOOL isUnconstrainedFlexBasis = ASRelativeDimensionEqualToRelativeDimension(ASRelativeDimensionUnconstrained, child.flexBasis);
|
||||||
const CGFloat exactStackDimension = ASRelativeDimensionResolve(child.layoutOptions.flexBasis, stackDimension(style.direction, size));
|
const CGFloat exactStackDimension = ASRelativeDimensionResolve(child.flexBasis, stackDimension(style.direction, size));
|
||||||
|
|
||||||
if (useOptimizedFlexing && isFlexibleInBothDirections(child)) {
|
if (useOptimizedFlexing && isFlexibleInBothDirections(child)) {
|
||||||
return { child, [ASLayout layoutWithLayoutableObject:child size:{0, 0}] };
|
return { child, [ASLayout layoutWithLayoutableObject:child size:{0, 0}] };
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ static NSString *suffixForCenteringOptions(ASCenterLayoutSpecCenteringOptions ce
|
|||||||
ASDisplayNode *backgroundNode = ASDisplayNodeWithBackgroundColor([UIColor redColor]);
|
ASDisplayNode *backgroundNode = ASDisplayNodeWithBackgroundColor([UIColor redColor]);
|
||||||
ASStaticSizeDisplayNode *foregroundNode = ASDisplayNodeWithBackgroundColor([UIColor redColor]);
|
ASStaticSizeDisplayNode *foregroundNode = ASDisplayNodeWithBackgroundColor([UIColor redColor]);
|
||||||
foregroundNode.staticSize = {10, 10};
|
foregroundNode.staticSize = {10, 10};
|
||||||
foregroundNode.layoutOptions.flexGrow = YES;
|
foregroundNode.flexGrow = YES;
|
||||||
|
|
||||||
ASCenterLayoutSpec *layoutSpec =
|
ASCenterLayoutSpec *layoutSpec =
|
||||||
[ASCenterLayoutSpec
|
[ASCenterLayoutSpec
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
];
|
];
|
||||||
for (ASStaticSizeDisplayNode *subnode in subnodes) {
|
for (ASStaticSizeDisplayNode *subnode in subnodes) {
|
||||||
subnode.staticSize = subnodeSize;
|
subnode.staticSize = subnodeSize;
|
||||||
subnode.layoutOptions.flexGrow = flex;
|
subnode.flexGrow = flex;
|
||||||
subnode.layoutOptions.flexShrink = flex;
|
subnode.flexShrink = flex;
|
||||||
}
|
}
|
||||||
return subnodes;
|
return subnodes;
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,7 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
ASStackLayoutSpecStyle style = {.direction = ASStackLayoutDirectionHorizontal};
|
ASStackLayoutSpecStyle style = {.direction = ASStackLayoutDirectionHorizontal};
|
||||||
|
|
||||||
NSArray *subnodes = defaultSubnodesWithSameSize({50, 50}, NO);
|
NSArray *subnodes = defaultSubnodesWithSameSize({50, 50}, NO);
|
||||||
((ASDisplayNode *)subnodes[1]).layoutOptions.flexShrink = YES;
|
((ASDisplayNode *)subnodes[1]).flexShrink = YES;
|
||||||
|
|
||||||
// Width is 75px--that's less than the sum of the widths of the children, which is 100px.
|
// 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}};
|
static ASSizeRange kSize = {{75, 0}, {75, 150}};
|
||||||
@@ -205,23 +205,23 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
|
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
|
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
|
||||||
|
|
||||||
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 10;
|
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 10;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 20;
|
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 20;
|
||||||
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingBefore"];
|
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingBefore"];
|
||||||
// Reset above spacing values
|
// Reset above spacing values
|
||||||
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 0;
|
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 0;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 0;
|
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 0;
|
||||||
|
|
||||||
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingAfter = 10;
|
((ASStaticSizeDisplayNode *)subnodes[1]).spacingAfter = 10;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingAfter = 20;
|
((ASStaticSizeDisplayNode *)subnodes[2]).spacingAfter = 20;
|
||||||
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingAfter"];
|
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingAfter"];
|
||||||
// Reset above spacing values
|
// Reset above spacing values
|
||||||
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingAfter = 0;
|
((ASStaticSizeDisplayNode *)subnodes[1]).spacingAfter = 0;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingAfter = 0;
|
((ASStaticSizeDisplayNode *)subnodes[2]).spacingAfter = 0;
|
||||||
|
|
||||||
style.spacing = 10;
|
style.spacing = 10;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = -10;
|
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = -10;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingAfter = -10;
|
((ASStaticSizeDisplayNode *)subnodes[1]).spacingAfter = -10;
|
||||||
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingBalancedOut"];
|
[self testStackLayoutSpecWithStyle:style sizeRange:kAnySize subnodes:subnodes identifier:@"spacingBalancedOut"];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,9 +237,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
|
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
|
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
|
||||||
|
|
||||||
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.spacingBefore = 0;
|
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 20;
|
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 30;
|
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30;
|
||||||
|
|
||||||
// width 0-300px; height 300px
|
// width 0-300px; height 300px
|
||||||
static ASSizeRange kVariableHeight = {{0, 300}, {300, 300}};
|
static ASSizeRange kVariableHeight = {{0, 300}, {300, 300}};
|
||||||
@@ -255,9 +255,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
subnode2.staticSize = {50, 50};
|
subnode2.staticSize = {50, 50};
|
||||||
|
|
||||||
ASRatioLayoutSpec *child1 = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.5 child:subnode1];
|
ASRatioLayoutSpec *child1 = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.5 child:subnode1];
|
||||||
child1.layoutOptions.flexBasis = ASRelativeDimensionMakeWithPercent(1);
|
child1.flexBasis = ASRelativeDimensionMakeWithPercent(1);
|
||||||
child1.layoutOptions.flexGrow = YES;
|
child1.flexGrow = YES;
|
||||||
child1.layoutOptions.flexShrink = YES;
|
child1.flexShrink = YES;
|
||||||
|
|
||||||
static ASSizeRange kFixedWidth = {{150, 0}, {150, INFINITY}};
|
static ASSizeRange kFixedWidth = {{150, 0}, {150, INFINITY}};
|
||||||
[self testStackLayoutSpecWithStyle:style children:@[child1, subnode2] sizeRange:kFixedWidth subnodes:@[subnode1, subnode2] identifier:nil];
|
[self testStackLayoutSpecWithStyle:style children:@[child1, subnode2] sizeRange:kFixedWidth subnodes:@[subnode1, subnode2] identifier:nil];
|
||||||
@@ -272,11 +272,11 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
|
|
||||||
ASStaticSizeDisplayNode *subnode1 = ASDisplayNodeWithBackgroundColor([UIColor redColor]);
|
ASStaticSizeDisplayNode *subnode1 = ASDisplayNodeWithBackgroundColor([UIColor redColor]);
|
||||||
subnode1.staticSize = {100, 100};
|
subnode1.staticSize = {100, 100};
|
||||||
subnode1.layoutOptions.flexShrink = YES;
|
subnode1.flexShrink = YES;
|
||||||
|
|
||||||
ASStaticSizeDisplayNode *subnode2 = ASDisplayNodeWithBackgroundColor([UIColor blueColor]);
|
ASStaticSizeDisplayNode *subnode2 = ASDisplayNodeWithBackgroundColor([UIColor blueColor]);
|
||||||
subnode2.staticSize = {50, 50};
|
subnode2.staticSize = {50, 50};
|
||||||
subnode2.layoutOptions.flexShrink = YES;
|
subnode2.flexShrink = YES;
|
||||||
|
|
||||||
NSArray *subnodes = @[subnode1, subnode2];
|
NSArray *subnodes = @[subnode1, subnode2];
|
||||||
static ASSizeRange kFixedWidth = {{150, 0}, {150, 100}};
|
static ASSizeRange kFixedWidth = {{150, 0}, {150, 100}};
|
||||||
@@ -292,7 +292,7 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
|
|
||||||
ASStaticSizeDisplayNode *subnode2 = ASDisplayNodeWithBackgroundColor([UIColor blueColor]);
|
ASStaticSizeDisplayNode *subnode2 = ASDisplayNodeWithBackgroundColor([UIColor blueColor]);
|
||||||
subnode2.staticSize = {50, 50};
|
subnode2.staticSize = {50, 50};
|
||||||
subnode2.layoutOptions.alignSelf = ASStackLayoutAlignSelfCenter;
|
subnode2.alignSelf = ASStackLayoutAlignSelfCenter;
|
||||||
|
|
||||||
NSArray *subnodes = @[subnode1, subnode2];
|
NSArray *subnodes = @[subnode1, subnode2];
|
||||||
static ASSizeRange kFixedWidth = {{150, 0}, {150, INFINITY}};
|
static ASSizeRange kFixedWidth = {{150, 0}, {150, INFINITY}};
|
||||||
@@ -312,9 +312,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
|
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
|
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
|
||||||
|
|
||||||
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.spacingBefore = 0;
|
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 20;
|
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 30;
|
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30;
|
||||||
|
|
||||||
static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
|
static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
|
||||||
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
|
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
|
||||||
@@ -333,9 +333,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
|
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
|
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
|
||||||
|
|
||||||
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.spacingBefore = 0;
|
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 20;
|
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 30;
|
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30;
|
||||||
|
|
||||||
static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
|
static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
|
||||||
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
|
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
|
||||||
@@ -354,9 +354,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
|
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
|
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
|
||||||
|
|
||||||
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.spacingBefore = 0;
|
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 20;
|
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 30;
|
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30;
|
||||||
|
|
||||||
static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
|
static ASSizeRange kExactSize = {{300, 300}, {300, 300}};
|
||||||
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
|
[self testStackLayoutSpecWithStyle:style sizeRange:kExactSize subnodes:subnodes identifier:nil];
|
||||||
@@ -375,9 +375,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
|
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
|
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
|
||||||
|
|
||||||
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.spacingBefore = 0;
|
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 20;
|
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 30;
|
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30;
|
||||||
|
|
||||||
static ASSizeRange kVariableSize = {{200, 200}, {300, 300}};
|
static ASSizeRange kVariableSize = {{200, 200}, {300, 300}};
|
||||||
// all children should be 200px wide
|
// all children should be 200px wide
|
||||||
@@ -397,9 +397,9 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
|
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 70};
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
|
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {150, 90};
|
||||||
|
|
||||||
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.spacingBefore = 0;
|
((ASStaticSizeDisplayNode *)subnodes[0]).spacingBefore = 0;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.spacingBefore = 20;
|
((ASStaticSizeDisplayNode *)subnodes[1]).spacingBefore = 20;
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.spacingBefore = 30;
|
((ASStaticSizeDisplayNode *)subnodes[2]).spacingBefore = 30;
|
||||||
|
|
||||||
static ASSizeRange kVariableSize = {{50, 50}, {300, 300}};
|
static ASSizeRange kVariableSize = {{50, 50}, {300, 300}};
|
||||||
// all children should be 150px wide
|
// all children should be 150px wide
|
||||||
@@ -420,8 +420,8 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {150, 150};
|
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {150, 150};
|
||||||
|
|
||||||
for (ASStaticSizeDisplayNode *subnode in subnodes) {
|
for (ASStaticSizeDisplayNode *subnode in subnodes) {
|
||||||
subnode.layoutOptions.flexGrow = YES;
|
subnode.flexGrow = YES;
|
||||||
subnode.layoutOptions.flexBasis = ASRelativeDimensionMakeWithPoints(10);
|
subnode.flexBasis = ASRelativeDimensionMakeWithPoints(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
// width 300px; height 0-150px.
|
// width 300px; height 0-150px.
|
||||||
@@ -440,12 +440,12 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
NSArray *subnodes = defaultSubnodesWithSameSize({50, 50}, NO);
|
NSArray *subnodes = defaultSubnodesWithSameSize({50, 50}, NO);
|
||||||
|
|
||||||
for (ASStaticSizeDisplayNode *subnode in subnodes) {
|
for (ASStaticSizeDisplayNode *subnode in subnodes) {
|
||||||
subnode.layoutOptions.flexGrow = YES;
|
subnode.flexGrow = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should override the intrinsic size of 50pts and instead compute to 50% = 100pts.
|
// 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.
|
// The result should be that the red box is twice as wide as the blue and gree boxes after flexing.
|
||||||
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.flexBasis = ASRelativeDimensionMakeWithPercent(0.5);
|
((ASStaticSizeDisplayNode *)subnodes[0]).flexBasis = ASRelativeDimensionMakeWithPercent(0.5);
|
||||||
|
|
||||||
static ASSizeRange kSize = {{200, 0}, {200, INFINITY}};
|
static ASSizeRange kSize = {{200, 0}, {200, INFINITY}};
|
||||||
[self testStackLayoutSpecWithStyle:style sizeRange:kSize subnodes:subnodes identifier:nil];
|
[self testStackLayoutSpecWithStyle:style sizeRange:kSize subnodes:subnodes identifier:nil];
|
||||||
@@ -461,7 +461,7 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {50, 50};
|
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {50, 50};
|
||||||
|
|
||||||
for (ASStaticSizeDisplayNode *subnode in subnodes) {
|
for (ASStaticSizeDisplayNode *subnode in subnodes) {
|
||||||
subnode.layoutOptions.flexBasis = ASRelativeDimensionMakeWithPoints(20);
|
subnode.flexBasis = ASRelativeDimensionMakeWithPoints(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ASSizeRange kSize = {{300, 0}, {300, 150}};
|
static ASSizeRange kSize = {{300, 0}, {300, 150}};
|
||||||
@@ -479,8 +479,8 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {3000, 3000};
|
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {3000, 3000};
|
||||||
|
|
||||||
ASRatioLayoutSpec *child2 = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.0 child:subnodes[2]];
|
ASRatioLayoutSpec *child2 = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1.0 child:subnodes[2]];
|
||||||
child2.layoutOptions.flexGrow = YES;
|
child2.flexGrow = YES;
|
||||||
child2.layoutOptions.flexShrink = YES;
|
child2.flexShrink = YES;
|
||||||
|
|
||||||
// If cross axis stretching occurred *before* flexing, then the blue child would be stretched to 3000 points tall.
|
// 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.
|
// Instead it should be stretched to 300 points tall, matching the red child and not overlapping the green inset.
|
||||||
@@ -505,13 +505,13 @@ static NSArray *defaultSubnodesWithSameSize(CGSize subnodeSize, BOOL flex)
|
|||||||
NSArray *subnodes = defaultSubnodes();
|
NSArray *subnodes = defaultSubnodes();
|
||||||
|
|
||||||
((ASStaticSizeDisplayNode *)subnodes[0]).staticSize = {300, 50};
|
((ASStaticSizeDisplayNode *)subnodes[0]).staticSize = {300, 50};
|
||||||
((ASStaticSizeDisplayNode *)subnodes[0]).layoutOptions.flexShrink = YES;
|
((ASStaticSizeDisplayNode *)subnodes[0]).flexShrink = YES;
|
||||||
|
|
||||||
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 50};
|
((ASStaticSizeDisplayNode *)subnodes[1]).staticSize = {100, 50};
|
||||||
((ASStaticSizeDisplayNode *)subnodes[1]).layoutOptions.flexShrink = NO;
|
((ASStaticSizeDisplayNode *)subnodes[1]).flexShrink = NO;
|
||||||
|
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {200, 50};
|
((ASStaticSizeDisplayNode *)subnodes[2]).staticSize = {200, 50};
|
||||||
((ASStaticSizeDisplayNode *)subnodes[2]).layoutOptions.flexShrink = YES;
|
((ASStaticSizeDisplayNode *)subnodes[2]).flexShrink = YES;
|
||||||
|
|
||||||
// A width of 400px results in a violation of 200px. This is distributed equally among each flexible child,
|
// 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.
|
// causing both of them to be shrunk by 100px, resulting in widths of 300px, 100px, and 50px.
|
||||||
|
|||||||
Reference in New Issue
Block a user