Let ASLayout determine if a node should measure

This commit is contained in:
Levi McCallum
2016-05-20 16:44:44 -07:00
parent c809609b01
commit f809d4a1c9
4 changed files with 26 additions and 15 deletions

View File

@@ -650,10 +650,15 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
}
}
// only calculate the size if
// - we haven't already
// - the constrained size range is different
return (!_flags.isMeasured || !ASSizeRangeEqualToSizeRange(constrainedSize, _layout.constrainedSizeRange));
// Only generate a new layout if:
// - The current layout is dirty
// - The passed constrained size is different than the layout's constrained size
return ([self _dirtyLayout] || !ASSizeRangeEqualToSizeRange(constrainedSize, _layout.constrainedSizeRange));
}
- (BOOL)_dirtyLayout
{
return _layout == nil || _layout.isDirty;
}
#pragma mark - Layout Transition
@@ -1019,7 +1024,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
ASDisplayNodeAssertThreadAffinity(self);
ASDN::MutexLocker l(_propertyLock);
if (!_flags.isMeasured) {
if ([self _dirtyLayout]) {
return;
}
@@ -1095,7 +1100,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
// Normally measure will be called before layout occurs. If this doesn't happen, nothing is going to call it at all.
// We simply call measureWithSizeRange: using a size range equal to whatever bounds were provided to that element or
// try to measure the node with the largest size as possible
if (self.supernode == nil && !self.supportsRangeManagedInterfaceState && !_flags.isMeasured) {
if (self.supernode == nil && !self.supportsRangeManagedInterfaceState && [self _dirtyLayout] == NO) {
if (CGRectEqualToRect(bounds, CGRectZero)) {
LOG(@"Warning: No size given for node before node was trying to layout itself: %@. Please provide a frame for the node.", self);
} else {
@@ -1108,7 +1113,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
{
ASDisplayNodeAssertMainThread();
if (!_flags.isMeasured) {
if ([self _dirtyLayout]) {
return;
}
@@ -2058,8 +2063,10 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
- (void)invalidateCalculatedLayout
{
ASDN::MutexLocker l(_propertyLock);
// This will cause -measureWithSizeRange: to actually compute the size instead of returning the previously cached size
_flags.isMeasured = NO;
// This will cause the next call to -measureWithSizeRange: to actually compute a new layout
// instead of returning the current layout
_layout.dirty = YES;
}
- (void)__didLoad
@@ -2395,8 +2402,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
}
}
- (void)applyLayout:(ASLayout *)layout
layoutContext:(ASLayoutTransition *)layoutContext
- (void)applyLayout:(ASLayout *)layout layoutContext:(ASLayoutTransition *)layoutContext
{
ASDN::MutexLocker l(_propertyLock);
_layout = layout;
@@ -2404,8 +2410,6 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
ASDisplayNodeAssertTrue(layout.layoutableObject == self);
ASDisplayNodeAssertTrue(layout.size.width >= 0.0);
ASDisplayNodeAssertTrue(layout.size.height >= 0.0);
_flags.isMeasured = YES;
if (self.usesImplicitHierarchyManagement && layoutContext != nil) {
[layoutContext applySubnodeInsertions];

View File

@@ -21,7 +21,9 @@ extern CGPoint const CGPointNull;
extern BOOL CGPointIsNull(CGPoint point);
/** Represents a computed immutable layout tree. */
/**
* A node in the layout tree that represents the size and position of the object that created it (ASLayoutable).
*/
@interface ASLayout : NSObject
/**
@@ -56,6 +58,11 @@ extern BOOL CGPointIsNull(CGPoint point);
*/
@property (nonatomic, readonly) NSArray<ASLayout *> *immediateSublayouts;
/**
* Mark the layout dirty for future regeneration.
*/
@property (nonatomic, getter=isDirty) BOOL dirty;
/**
* A boolean describing if the current layout has been flattened.
*/

View File

@@ -50,6 +50,7 @@ extern BOOL CGPointIsNull(CGPoint point)
}
l->_constrainedSizeRange = sizeRange;
l->_size = size;
l->_dirty = NO;
if (CGPointIsNull(position) == NO) {
l->_position = CGPointMake(ASCeilPixelValue(position.x), ASCeilPixelValue(position.y));

View File

@@ -82,7 +82,6 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
unsigned implementsDrawParameters:1;
// internal state
unsigned isMeasured:1;
unsigned isEnteringHierarchy:1;
unsigned isExitingHierarchy:1;
unsigned isInHierarchy:1;