mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-20 21:29:00 +00:00
Some more changes
This commit is contained in:
parent
c819d716b4
commit
0eb882bae5
@ -29,7 +29,7 @@
|
|||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark ASCellNode
|
#pragma mark ASCellNode
|
||||||
|
|
||||||
@interface ASCellNode () <ASDisplayNodeSizingDelegate>
|
@interface ASCellNode ()
|
||||||
{
|
{
|
||||||
ASDisplayNodeViewControllerBlock _viewControllerBlock;
|
ASDisplayNodeViewControllerBlock _viewControllerBlock;
|
||||||
ASDisplayNodeDidLoadBlock _viewControllerDidLoadBlock;
|
ASDisplayNodeDidLoadBlock _viewControllerDidLoadBlock;
|
||||||
@ -59,9 +59,6 @@ static NSMutableSet *__cellClassesForVisibilityNotifications = nil; // See +init
|
|||||||
_selectionStyle = UITableViewCellSelectionStyleDefault;
|
_selectionStyle = UITableViewCellSelectionStyleDefault;
|
||||||
self.clipsToBounds = YES;
|
self.clipsToBounds = YES;
|
||||||
|
|
||||||
// ASCellNode acts as sizing container for the node
|
|
||||||
self.sizingDelegate = self;
|
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,19 +118,16 @@ static NSMutableSet *__cellClassesForVisibilityNotifications = nil; // See +init
|
|||||||
_viewControllerNode.frame = self.bounds;
|
_viewControllerNode.frame = self.bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)displayNodeDidInvalidateSize:(ASDisplayNode *)displayNode
|
- (void)didInvalidateSize
|
||||||
{
|
{
|
||||||
ASDN::MutexLocker l(__instanceLock__);
|
// TODO: coalesc: Ask the UITableView for the proper constrained size it can layout
|
||||||
|
|
||||||
CGSize oldSize = self.calculatedSize;
|
CGSize oldSize = self.calculatedSize;
|
||||||
ASLayout *layout = [self layoutThatFits:self.constrainedSizeForCalculatedLayout];
|
CGSize newSize = [self sizeThatFits:CGSizeMake(CGRectGetWidth(self.bounds), CGFLOAT_MAX)];
|
||||||
|
|
||||||
// TODO: Needs proper adjustment
|
if (CGSizeEqualToSize(oldSize, newSize) == NO) {
|
||||||
CGRect f = self.frame;
|
self.frame = {self.frame.origin, newSize};
|
||||||
f.size = layout.size;
|
[self didRelayoutFromOldSize:oldSize toNewSize:newSize];
|
||||||
self.frame = f;
|
}
|
||||||
|
|
||||||
[self didRelayoutFromOldSize:oldSize toNewSize:layout.size];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)transitionLayoutWithAnimation:(BOOL)animated
|
- (void)transitionLayoutWithAnimation:(BOOL)animated
|
||||||
|
|||||||
@ -765,7 +765,9 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
|||||||
|
|
||||||
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
|
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
|
||||||
{
|
{
|
||||||
return [[self nodeForItemAtIndexPath:indexPath] calculatedSize];
|
ASDisplayNode *node = [self nodeForItemAtIndexPath:indexPath];
|
||||||
|
[node layoutIfNeeded];
|
||||||
|
return node.calculatedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||||
|
|||||||
@ -267,8 +267,9 @@ extern NSInteger const ASDefaultDrawingPriority;
|
|||||||
|
|
||||||
/** @name Managing dimensions */
|
/** @name Managing dimensions */
|
||||||
|
|
||||||
@property (nonatomic, readwrite, weak, nullable) id<ASDisplayNodeSizingDelegate> sizingDelegate;
|
//@property (nonatomic, readwrite, weak, nullable) id<ASDisplayNodeSizingDelegate> sizingDelegate;
|
||||||
- (void)invalidateSize;
|
- (void)invalidateSize;
|
||||||
|
- (void)didInvalidateSize;
|
||||||
- (void)sizeToFit;
|
- (void)sizeToFit;
|
||||||
|
|
||||||
- (CGSize)sizeThatFits:(CGSize)size;
|
- (CGSize)sizeThatFits:(CGSize)size;
|
||||||
|
|||||||
@ -709,14 +709,18 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
|
|
||||||
__instanceLock__.lock();
|
__instanceLock__.lock();
|
||||||
|
|
||||||
|
// Mark the node for layout in the next layout pass
|
||||||
[self invalidateCalculatedLayout];
|
[self invalidateCalculatedLayout];
|
||||||
|
|
||||||
// This is the root node. Let the delegate know that the size changed
|
// This is the root node. Let the delegate know that the size changed
|
||||||
// If someone calls `invalidateBlaBla TBD` we have to inform the sizing delegate of the root node to be able
|
// If someone calls `invalidateBlaBla TBD` we have to inform the sizing delegate of the root node to be able
|
||||||
// to let them now that a size change happened and it needs to calculate a new layout / size for this node hierarchy
|
// to let them now that a size change happened and it needs to calculate a new layout / size for this node hierarchy
|
||||||
if ([self.sizingDelegate respondsToSelector:@selector(displayNodeDidInvalidateSize:)]) {
|
// if ([self.sizingDelegate respondsToSelector:@selector(displayNodeDidInvalidateSize:)]) {
|
||||||
[self.sizingDelegate displayNodeDidInvalidateSize:self];
|
// [self.sizingDelegate displayNodeDidInvalidateSize:self];
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// Hook for subclasses to get size invalidation changes
|
||||||
|
[self didInvalidateSize];
|
||||||
|
|
||||||
if (_supernode) {
|
if (_supernode) {
|
||||||
ASDisplayNode *supernode = _supernode;
|
ASDisplayNode *supernode = _supernode;
|
||||||
@ -727,9 +731,17 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We are now at the root node trigger a layout pass
|
||||||
|
[self setNeedsLayout];
|
||||||
|
|
||||||
__instanceLock__.unlock();
|
__instanceLock__.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)didInvalidateSize
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
- (void)sizeToFit
|
- (void)sizeToFit
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssertThreadAffinity(self);
|
ASDisplayNodeAssertThreadAffinity(self);
|
||||||
@ -739,11 +751,10 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
[self setNeedsLayout];
|
[self setNeedsLayout];
|
||||||
|
|
||||||
CGSize maxSize = _supernode ? _supernode.bounds.size : CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX);
|
CGSize maxSize = _supernode ? _supernode.bounds.size : CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX);
|
||||||
CGSize size = [self sizeThatFits:maxSize];
|
CGSize newSize = [self sizeThatFits:maxSize];
|
||||||
|
|
||||||
CGRect oldBounds = self.bounds;
|
CGRect oldBounds = self.bounds;
|
||||||
CGSize oldSize = oldBounds.size;
|
CGSize oldSize = oldBounds.size;
|
||||||
CGSize newSize = _calculatedDisplayNodeLayout->layout.size;
|
|
||||||
|
|
||||||
if (! CGSizeEqualToSize(oldSize, newSize)) {
|
if (! CGSizeEqualToSize(oldSize, newSize)) {
|
||||||
self.bounds = (CGRect){ oldBounds.origin, newSize };
|
self.bounds = (CGRect){ oldBounds.origin, newSize };
|
||||||
@ -777,74 +788,12 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
{
|
{
|
||||||
ASDN::MutexLocker l(__instanceLock__);
|
ASDN::MutexLocker l(__instanceLock__);
|
||||||
|
|
||||||
if ([self shouldCalculateLayoutWithConstrainedSize:constrainedSize parentSize:parentSize] == NO) {
|
if (_calculatedDisplayNodeLayout->isValidForConstrainedSizeParentSize(constrainedSize, parentSize)) {
|
||||||
ASDisplayNodeAssertNotNil(_calculatedDisplayNodeLayout->layout, @"-[ASDisplayNode layoutThatFits:parentSize:] _layout should not be nil! %@", self);
|
ASDisplayNodeAssertNotNil(_calculatedDisplayNodeLayout->layout, @"-[ASDisplayNode layoutThatFits:parentSize:] _layout should not be nil! %@", self);
|
||||||
return _calculatedDisplayNodeLayout->layout ? : [ASLayout layoutWithLayoutElement:self size:{0, 0}];
|
return _calculatedDisplayNodeLayout->layout ? : [ASLayout layoutWithLayoutElement:self size:{0, 0}];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self cancelLayoutTransition];
|
return [self calculateLayoutThatFits:constrainedSize restrictedToSize:self.style.size relativeToParentSize:parentSize];
|
||||||
|
|
||||||
BOOL didCreateNewContext = NO;
|
|
||||||
BOOL didOverrideExistingContext = NO;
|
|
||||||
BOOL shouldVisualizeLayout = ASHierarchyStateIncludesVisualizeLayout(_hierarchyState);
|
|
||||||
ASLayoutElementContext context;
|
|
||||||
if (ASLayoutElementContextIsNull(ASLayoutElementGetCurrentContext())) {
|
|
||||||
context = ASLayoutElementContextMake(ASLayoutElementContextDefaultTransitionID, shouldVisualizeLayout);
|
|
||||||
ASLayoutElementSetCurrentContext(context);
|
|
||||||
didCreateNewContext = YES;
|
|
||||||
} else {
|
|
||||||
context = ASLayoutElementGetCurrentContext();
|
|
||||||
if (context.needsVisualizeNode != shouldVisualizeLayout) {
|
|
||||||
context.needsVisualizeNode = shouldVisualizeLayout;
|
|
||||||
ASLayoutElementSetCurrentContext(context);
|
|
||||||
didOverrideExistingContext = YES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare for layout transition
|
|
||||||
auto previousLayout = _calculatedDisplayNodeLayout;
|
|
||||||
auto pendingLayout = std::make_shared<ASDisplayNodeLayout>(
|
|
||||||
[self calculateLayoutThatFits:constrainedSize restrictedToSize:self.style.size relativeToParentSize:parentSize],
|
|
||||||
constrainedSize,
|
|
||||||
parentSize
|
|
||||||
);
|
|
||||||
|
|
||||||
if (didCreateNewContext) {
|
|
||||||
ASLayoutElementClearCurrentContext();
|
|
||||||
} else if (didOverrideExistingContext) {
|
|
||||||
context.needsVisualizeNode = !context.needsVisualizeNode;
|
|
||||||
ASLayoutElementSetCurrentContext(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
_pendingLayoutTransition = [[ASLayoutTransition alloc] initWithNode:self
|
|
||||||
pendingLayout:pendingLayout
|
|
||||||
previousLayout:previousLayout];
|
|
||||||
|
|
||||||
// Only complete the pending layout transition if the node is not a subnode of a node that is currently
|
|
||||||
// in a layout transition
|
|
||||||
if (ASHierarchyStateIncludesLayoutPending(_hierarchyState) == NO) {
|
|
||||||
// Complete the pending layout transition immediately
|
|
||||||
[self _completePendingLayoutTransition];
|
|
||||||
}
|
|
||||||
|
|
||||||
ASDisplayNodeAssertNotNil(pendingLayout->layout, @"-[ASDisplayNode layoutThatFits:parentSize:] newLayout should not be nil! %@", self);
|
|
||||||
return pendingLayout->layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)shouldCalculateLayoutWithConstrainedSize:(ASSizeRange)constrainedSize parentSize:(CGSize)parentSize
|
|
||||||
{
|
|
||||||
ASDN::MutexLocker l(__instanceLock__);
|
|
||||||
|
|
||||||
// Don't remeasure if in layout pending state and a new transition already started
|
|
||||||
if (ASHierarchyStateIncludesLayoutPending(_hierarchyState)) {
|
|
||||||
ASLayoutElementContext context = ASLayoutElementGetCurrentContext();
|
|
||||||
if (ASLayoutElementContextIsNull(context) || _pendingTransitionID != context.transitionID) {
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if display node layout is still valid
|
|
||||||
return _calculatedDisplayNodeLayout->isValidForConstrainedSizeParentSize(constrainedSize, parentSize) == NO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ASLayoutElementType)layoutElementType
|
- (ASLayoutElementType)layoutElementType
|
||||||
@ -883,7 +832,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[self invalidateCalculatedLayout];
|
[self setNeedsLayout];
|
||||||
[self transitionLayoutWithSizeRange:_calculatedDisplayNodeLayout->constrainedSize
|
[self transitionLayoutWithSizeRange:_calculatedDisplayNodeLayout->constrainedSize
|
||||||
animated:animated
|
animated:animated
|
||||||
shouldMeasureAsync:shouldMeasureAsync
|
shouldMeasureAsync:shouldMeasureAsync
|
||||||
@ -898,7 +847,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
{
|
{
|
||||||
// Passed constrainedSize is the the same as the node's current constrained size it's a noop
|
// Passed constrainedSize is the the same as the node's current constrained size it's a noop
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
if ([self shouldCalculateLayoutWithConstrainedSize:constrainedSize parentSize:constrainedSize.max] == NO) {
|
if (_calculatedDisplayNodeLayout->isValidForConstrainedSizeParentSize(constrainedSize, constrainedSize.max)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1449,13 +1398,18 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
[self displayImmediately];
|
[self displayImmediately];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)invalidateCalculatedLayout
|
||||||
|
{
|
||||||
|
// This will cause the next layout pass to compute a new layout instead of returning
|
||||||
|
// the cached layout in case the constrained or parent size did not change
|
||||||
|
_calculatedDisplayNodeLayout->invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
- (void)__setNeedsLayout
|
- (void)__setNeedsLayout
|
||||||
{
|
{
|
||||||
ASDN::MutexLocker l(__instanceLock__);
|
ASDN::MutexLocker l(__instanceLock__);
|
||||||
|
|
||||||
// This will cause the next call to -layoutThatFits:parentSize: to compute a new layout instead of returning
|
[self invalidateCalculatedLayout];
|
||||||
// the cached layout in case the constrained or parent size did not change
|
|
||||||
_calculatedDisplayNodeLayout->invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1482,7 +1436,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
[supernode __layoutIfNeeded];
|
[supernode __layoutIfNeeded];
|
||||||
} else {
|
} else {
|
||||||
// Layout all subviews starting from the first node that needs layout
|
// Layout all subviews starting from the first node that needs layout
|
||||||
[self __layout];
|
[self __layoutSublayers];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1498,13 +1452,11 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
|
|
||||||
// These private methods ensure that subclasses are not required to call super in order for _renderingSubnodes to be properly managed.
|
// These private methods ensure that subclasses are not required to call super in order for _renderingSubnodes to be properly managed.
|
||||||
|
|
||||||
- (void)__layout
|
- (void)__layoutSublayers
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
ASDN::MutexLocker l(__instanceLock__);
|
ASDN::MutexLocker l(__instanceLock__);
|
||||||
CGRect bounds = self.bounds;
|
CGRect bounds = _threadSafeBounds;
|
||||||
|
|
||||||
[self measureNodeWithBoundsIfNecessary:bounds];
|
|
||||||
|
|
||||||
if (CGRectEqualToRect(bounds, CGRectZero)) {
|
if (CGRectEqualToRect(bounds, CGRectZero)) {
|
||||||
// Performing layout on a zero-bounds view often results in frame calculations
|
// Performing layout on a zero-bounds view often results in frame calculations
|
||||||
@ -1513,6 +1465,8 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[self measureNodeWithBoundsIfNecessary:bounds];
|
||||||
|
|
||||||
// Handle placeholder layer creation in case the size of the node changed after the initial placeholder layer
|
// Handle placeholder layer creation in case the size of the node changed after the initial placeholder layer
|
||||||
// was created
|
// was created
|
||||||
if ([self _shouldHavePlaceholderLayer]) {
|
if ([self _shouldHavePlaceholderLayer]) {
|
||||||
@ -1524,18 +1478,9 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
[self layoutDidFinish];
|
[self layoutDidFinish];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Needs to be called with lock held
|
||||||
- (void)measureNodeWithBoundsIfNecessary:(CGRect)bounds
|
- (void)measureNodeWithBoundsIfNecessary:(CGRect)bounds
|
||||||
{
|
{
|
||||||
BOOL supportsRangeManagedInterfaceState = NO;
|
|
||||||
BOOL hasDirtyLayout = NO;
|
|
||||||
CGSize calculatedLayoutSize = CGSizeZero;
|
|
||||||
{
|
|
||||||
ASDN::MutexLocker l(__instanceLock__);
|
|
||||||
supportsRangeManagedInterfaceState = [self supportsRangeManagedInterfaceState];
|
|
||||||
hasDirtyLayout = _calculatedDisplayNodeLayout->isDirty();
|
|
||||||
calculatedLayoutSize = _calculatedDisplayNodeLayout->layout.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if it's a subnode in a layout transition. In this case no measurement is needed as it's part of
|
// Check if it's a subnode in a layout transition. In this case no measurement is needed as it's part of
|
||||||
// the layout transition
|
// the layout transition
|
||||||
if (ASHierarchyStateIncludesLayoutPending(_hierarchyState)) {
|
if (ASHierarchyStateIncludesLayoutPending(_hierarchyState)) {
|
||||||
@ -1549,8 +1494,60 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
// for the node using a size range equal to whatever bounds were provided to the node
|
// for the node using a size range equal to whatever bounds were provided to the node
|
||||||
if (CGRectEqualToRect(bounds, CGRectZero)) {
|
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);
|
LOG(@"Warning: No size given for node before node was trying to layout itself: %@. Please provide a frame for the node.", self);
|
||||||
} else if (hasDirtyLayout || CGSizeEqualToSize(calculatedLayoutSize, bounds.size) == NO) {
|
return;
|
||||||
[self layoutThatFits:ASSizeRangeMake(bounds.size)];
|
}
|
||||||
|
|
||||||
|
if (_calculatedDisplayNodeLayout->isDirty() ||
|
||||||
|
CGSizeEqualToSize(_calculatedDisplayNodeLayout->layout.size, bounds.size) == NO)
|
||||||
|
{
|
||||||
|
[self cancelLayoutTransition];
|
||||||
|
|
||||||
|
BOOL didCreateNewContext = NO;
|
||||||
|
BOOL didOverrideExistingContext = NO;
|
||||||
|
BOOL shouldVisualizeLayout = ASHierarchyStateIncludesVisualizeLayout(_hierarchyState);
|
||||||
|
ASLayoutElementContext context;
|
||||||
|
if (ASLayoutElementContextIsNull(ASLayoutElementGetCurrentContext())) {
|
||||||
|
context = ASLayoutElementContextMake(ASLayoutElementContextDefaultTransitionID, shouldVisualizeLayout);
|
||||||
|
ASLayoutElementSetCurrentContext(context);
|
||||||
|
didCreateNewContext = YES;
|
||||||
|
} else {
|
||||||
|
context = ASLayoutElementGetCurrentContext();
|
||||||
|
if (context.needsVisualizeNode != shouldVisualizeLayout) {
|
||||||
|
context.needsVisualizeNode = shouldVisualizeLayout;
|
||||||
|
ASLayoutElementSetCurrentContext(context);
|
||||||
|
didOverrideExistingContext = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare for layout transition
|
||||||
|
CGSize parentSize = bounds.size;
|
||||||
|
ASSizeRange constrainedSize = ASSizeRangeMake(parentSize);
|
||||||
|
auto previousLayout = _calculatedDisplayNodeLayout;
|
||||||
|
auto pendingLayout = std::make_shared<ASDisplayNodeLayout>(
|
||||||
|
[self calculateLayoutThatFits:constrainedSize restrictedToSize:self.style.size relativeToParentSize:parentSize],
|
||||||
|
constrainedSize,
|
||||||
|
parentSize
|
||||||
|
);
|
||||||
|
|
||||||
|
if (didCreateNewContext) {
|
||||||
|
ASLayoutElementClearCurrentContext();
|
||||||
|
} else if (didOverrideExistingContext) {
|
||||||
|
context.needsVisualizeNode = !context.needsVisualizeNode;
|
||||||
|
ASLayoutElementSetCurrentContext(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASDisplayNodeAssertNotNil(pendingLayout->layout, @"pendintLayout->layout should not be nil! %@", self);
|
||||||
|
|
||||||
|
_pendingLayoutTransition = [[ASLayoutTransition alloc] initWithNode:self
|
||||||
|
pendingLayout:pendingLayout
|
||||||
|
previousLayout:previousLayout];
|
||||||
|
|
||||||
|
// Only complete the pending layout transition if the node is not a subnode of a node that is currently
|
||||||
|
// in a layout transition
|
||||||
|
if (ASHierarchyStateIncludesLayoutPending(_hierarchyState) == NO) {
|
||||||
|
// Complete the pending layout transition immediately
|
||||||
|
[self _completePendingLayoutTransition];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2680,15 +2677,6 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)invalidateCalculatedLayout
|
|
||||||
{
|
|
||||||
ASDN::MutexLocker l(__instanceLock__);
|
|
||||||
|
|
||||||
// This will cause the next call to -layoutThatFits:parentSize: to compute a new layout instead of returning
|
|
||||||
// the cached layout in case the constrained or parent size did not change
|
|
||||||
_calculatedDisplayNodeLayout->invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)__didLoad
|
- (void)__didLoad
|
||||||
{
|
{
|
||||||
ASDN::MutexLocker l(__instanceLock__);
|
ASDN::MutexLocker l(__instanceLock__);
|
||||||
@ -3730,7 +3718,7 @@ static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode";
|
|||||||
{
|
{
|
||||||
// Deprecated preferredFrameSize just calls through to set width and height
|
// Deprecated preferredFrameSize just calls through to set width and height
|
||||||
self.style.preferredSize = preferredFrameSize;
|
self.style.preferredSize = preferredFrameSize;
|
||||||
[self invalidateCalculatedLayout];
|
[self setNeedsLayout];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGSize)preferredFrameSize
|
- (CGSize)preferredFrameSize
|
||||||
|
|||||||
@ -204,7 +204,7 @@ struct ASImageNodeDrawParameters {
|
|||||||
if (!ASObjectIsEqual(_image, image)) {
|
if (!ASObjectIsEqual(_image, image)) {
|
||||||
_image = image;
|
_image = image;
|
||||||
|
|
||||||
[self invalidateCalculatedLayout];
|
[self setNeedsLayout];
|
||||||
if (image) {
|
if (image) {
|
||||||
[self setNeedsDisplay];
|
[self setNeedsDisplay];
|
||||||
|
|
||||||
|
|||||||
@ -751,6 +751,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
|||||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
|
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||||
{
|
{
|
||||||
ASCellNode *node = [_dataController nodeAtIndexPath:indexPath];
|
ASCellNode *node = [_dataController nodeAtIndexPath:indexPath];
|
||||||
|
[node layoutIfNeeded];
|
||||||
return node.calculatedSize.height;
|
return node.calculatedSize.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1509,8 +1510,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
|||||||
|
|
||||||
#pragma mark - _ASTableViewCellDelegate
|
#pragma mark - _ASTableViewCellDelegate
|
||||||
|
|
||||||
#pragma mark - _ASTableViewCellDelegate
|
|
||||||
|
|
||||||
- (void)didLayoutSubviewsOfTableViewCell:(_ASTableViewCell *)tableViewCell
|
- (void)didLayoutSubviewsOfTableViewCell:(_ASTableViewCell *)tableViewCell
|
||||||
{
|
{
|
||||||
ASCellNode *node = tableViewCell.node;
|
ASCellNode *node = tableViewCell.node;
|
||||||
@ -1525,7 +1524,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
|||||||
// Normally the content view width equals to the constrained size width (which equals to the table view width).
|
// Normally the content view width equals to the constrained size width (which equals to the table view width).
|
||||||
// If there is a mismatch between these values, for example after the table view entered or left editing mode,
|
// If there is a mismatch between these values, for example after the table view entered or left editing mode,
|
||||||
// content view width is preferred and used to re-measure the cell node.
|
// content view width is preferred and used to re-measure the cell node.
|
||||||
if (contentViewWidth != constrainedSize.max.width) {
|
if (CGSizeEqualToSize(node.calculatedSize, CGSizeZero) == NO && contentViewWidth != constrainedSize.max.width) {
|
||||||
constrainedSize.min.width = contentViewWidth;
|
constrainedSize.min.width = contentViewWidth;
|
||||||
constrainedSize.max.width = contentViewWidth;
|
constrainedSize.max.width = contentViewWidth;
|
||||||
|
|
||||||
|
|||||||
@ -330,8 +330,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
|||||||
BOOL needsUpdate = !UIEdgeInsetsEqualToEdgeInsets(textContainerInset, _textContainerInset);
|
BOOL needsUpdate = !UIEdgeInsetsEqualToEdgeInsets(textContainerInset, _textContainerInset);
|
||||||
if (needsUpdate) {
|
if (needsUpdate) {
|
||||||
_textContainerInset = textContainerInset;
|
_textContainerInset = textContainerInset;
|
||||||
[self invalidateCalculatedLayout];
|
[self invalidateSize];
|
||||||
[self setNeedsLayout];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,7 +486,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tell the display node superclasses that the cached layout is incorrect now
|
// Tell the display node superclasses that the cached layout is incorrect now
|
||||||
[self invalidateCalculatedLayout];
|
[self invalidateSize];
|
||||||
|
|
||||||
// Force display to create renderer with new size and redisplay with new string
|
// Force display to create renderer with new size and redisplay with new string
|
||||||
[self setNeedsDisplay];
|
[self setNeedsDisplay];
|
||||||
@ -510,7 +509,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
|||||||
|
|
||||||
_exclusionPaths = [exclusionPaths copy];
|
_exclusionPaths = [exclusionPaths copy];
|
||||||
[self _invalidateRenderer];
|
[self _invalidateRenderer];
|
||||||
[self invalidateCalculatedLayout];
|
[self invalidateSize];
|
||||||
[self setNeedsDisplay];
|
[self setNeedsDisplay];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -135,7 +135,7 @@
|
|||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
[super layoutSublayers];
|
[super layoutSublayers];
|
||||||
|
|
||||||
[self.asyncdisplaykit_node __layout];
|
[self.asyncdisplaykit_node __layoutSublayers];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setNeedsDisplay
|
- (void)setNeedsDisplay
|
||||||
|
|||||||
@ -52,7 +52,7 @@
|
|||||||
|
|
||||||
// if super node is rasterizing descendants, subnodes will not have had layout calls because they don't have layers
|
// if super node is rasterizing descendants, subnodes will not have had layout calls because they don't have layers
|
||||||
if (rasterizingFromAscendent) {
|
if (rasterizingFromAscendent) {
|
||||||
[self __layout];
|
[self __layoutSublayers];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Capture these outside the display block so they are retained.
|
// Capture these outside the display block so they are retained.
|
||||||
|
|||||||
@ -212,7 +212,7 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
|
|||||||
*/
|
*/
|
||||||
- (void)__setNeedsDisplay;
|
- (void)__setNeedsDisplay;
|
||||||
|
|
||||||
- (void)__layout;
|
- (void)__layoutSublayers;
|
||||||
- (void)__setSupernode:(ASDisplayNode *)supernode;
|
- (void)__setSupernode:(ASDisplayNode *)supernode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
#import "DetailRootNode.h"
|
#import "DetailRootNode.h"
|
||||||
#import "SampleSizingNode.h"
|
#import "SampleSizingNode.h"
|
||||||
|
|
||||||
@interface DetailViewController () <ASDisplayNodeSizingDelegate>
|
@interface DetailViewController ()// <ASDisplayNodeSizingDelegate>
|
||||||
@property (strong, nonatomic) SampleSizingNode *sizingNode;
|
@property (strong, nonatomic) SampleSizingNode *sizingNode;
|
||||||
|
|
||||||
@property (strong, nonatomic) ASNetworkImageNode *imageNode;
|
@property (strong, nonatomic) ASNetworkImageNode *imageNode;
|
||||||
@ -40,7 +40,7 @@
|
|||||||
// Set the sizing delegate of the root node to the container
|
// Set the sizing delegate of the root node to the container
|
||||||
_sizingNode = [SampleSizingNode new];
|
_sizingNode = [SampleSizingNode new];
|
||||||
_sizingNode.autoresizingMask = UIViewAutoresizingNone;
|
_sizingNode.autoresizingMask = UIViewAutoresizingNone;
|
||||||
_sizingNode.sizingDelegate = self;
|
//_sizingNode.sizingDelegate = self;
|
||||||
|
|
||||||
_imageNode = [ASNetworkImageNode new];
|
_imageNode = [ASNetworkImageNode new];
|
||||||
_imageNode.needsDisplayOnBoundsChange = YES;
|
_imageNode.needsDisplayOnBoundsChange = YES;
|
||||||
@ -53,7 +53,7 @@
|
|||||||
[_buttonNode setTitle:@"Some Title" withFont:nil withColor:nil forState:ASControlStateNormal];
|
[_buttonNode setTitle:@"Some Title" withFont:nil withColor:nil forState:ASControlStateNormal];
|
||||||
[_buttonNode setTitle:@"Some Bla" withFont:nil withColor:[UIColor orangeColor] forState:ASControlStateHighlighted];
|
[_buttonNode setTitle:@"Some Bla" withFont:nil withColor:[UIColor orangeColor] forState:ASControlStateHighlighted];
|
||||||
[_buttonNode addTarget:self action:@selector(buttonAction:) forControlEvents:ASControlNodeEventTouchUpInside];
|
[_buttonNode addTarget:self action:@selector(buttonAction:) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||||
_buttonNode.sizingDelegate = self;
|
//_buttonNode.sizingDelegate = self;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@
|
|||||||
// Initial size of sizing node
|
// Initial size of sizing node
|
||||||
//self.sizingNode.frame = CGRectMake(100, 100, 50, 50);
|
//self.sizingNode.frame = CGRectMake(100, 100, 50, 50);
|
||||||
|
|
||||||
[self displayNodeDidInvalidateSize:self.buttonNode];
|
//[self displayNodeDidInvalidateSize:self.buttonNode];
|
||||||
|
|
||||||
// Initial size for image node
|
// Initial size for image node
|
||||||
// self.imageNode.frame = CGRectMake(50, 70, 100, 100);
|
// self.imageNode.frame = CGRectMake(50, 70, 100, 100);
|
||||||
@ -94,6 +94,7 @@
|
|||||||
{
|
{
|
||||||
[super viewDidLayoutSubviews];
|
[super viewDidLayoutSubviews];
|
||||||
|
|
||||||
|
// Updat the sizing for the button node
|
||||||
[self updateButtonNodeLayout];
|
[self updateButtonNodeLayout];
|
||||||
|
|
||||||
// Update the sizing node layout
|
// Update the sizing node layout
|
||||||
@ -116,23 +117,23 @@
|
|||||||
|
|
||||||
// The sizing delegate will get callbacks if the size did invalidate of the display node. It's the job of the delegate
|
// The sizing delegate will get callbacks if the size did invalidate of the display node. It's the job of the delegate
|
||||||
// to get the new size from the display node and update the frame based on the returned size
|
// to get the new size from the display node and update the frame based on the returned size
|
||||||
- (void)displayNodeDidInvalidateSize:(ASDisplayNode *)displayNode
|
//- (void)displayNodeDidInvalidateSize:(ASDisplayNode *)displayNode
|
||||||
{
|
//{
|
||||||
if (displayNode == self.buttonNode) {
|
// if (displayNode == self.buttonNode) {
|
||||||
[self updateButtonNodeLayout];
|
// [self updateButtonNodeLayout];
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
[self updateNodeLayout];
|
// [self updateNodeLayout];
|
||||||
|
//
|
||||||
/*dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
// /*dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
[self updateNodeLayoutRandom];
|
// [self updateNodeLayoutRandom];
|
||||||
});*/
|
// });*/
|
||||||
|
//
|
||||||
/*[NSTimer scheduledTimerWithTimeInterval:2.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
|
// /*[NSTimer scheduledTimerWithTimeInterval:2.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
|
||||||
[self updateNodeLayoutRandom];
|
// [self updateNodeLayoutRandom];
|
||||||
}];*/
|
// }];*/
|
||||||
}
|
//}
|
||||||
|
|
||||||
- (void)updateNodeLayout
|
- (void)updateNodeLayout
|
||||||
{
|
{
|
||||||
@ -140,29 +141,34 @@
|
|||||||
//return;
|
//return;
|
||||||
// Use the bounds of the view and get the fitting size
|
// Use the bounds of the view and get the fitting size
|
||||||
// This does not have any side effects, but can be called on the main thread without any problems
|
// This does not have any side effects, but can be called on the main thread without any problems
|
||||||
CGSize size = [self.sizingNode sizeThatFits:CGSizeMake(CGFLOAT_MAX, 100.0)];
|
CGSize size = [self.sizingNode sizeThatFits:CGSizeMake(INFINITY, 100.0)];
|
||||||
//size.width -= 10;
|
//size.width -= 10;
|
||||||
//[self.sizingNode setNeedsLayout];
|
//[self.sizingNode setNeedsLayout];
|
||||||
self.sizingNode.frame = CGRectMake((self.view.bounds.size.width - size.width) / 2.0,
|
self.sizingNode.frame = CGRectMake((CGRectGetWidth(self.view.bounds) - size.width) / 2.0,
|
||||||
(self.view.bounds.size.height - size.height) / 2.0,
|
(CGRectGetHeight(self.view.bounds) - size.height) / 2.0,
|
||||||
size.width, size.height);
|
size.width,
|
||||||
|
size.height);
|
||||||
|
|
||||||
//dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
//dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
|
// Decrease the frame a bit
|
||||||
self.sizingNode.frame = CGRectInset(self.sizingNode.frame, 10, 10);
|
self.sizingNode.frame = CGRectInset(self.sizingNode.frame, 10, 10);
|
||||||
//});
|
//});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateNodeLayoutRandom
|
- (void)updateNodeLayoutRandom
|
||||||
{
|
{
|
||||||
|
CGRect bounds = self.view.bounds;
|
||||||
|
|
||||||
// Pick a randome width and height and set the frame of the node
|
// Pick a randome width and height and set the frame of the node
|
||||||
CGSize size = CGSizeZero;
|
CGSize size = CGSizeZero;
|
||||||
size.width = arc4random_uniform(self.view.bounds.size.width);
|
size.width = arc4random_uniform(CGRectGetWidth(bounds));
|
||||||
size.height = arc4random_uniform(self.view.bounds.size.height);
|
size.height = arc4random_uniform(CGRectGetHeight(bounds));
|
||||||
|
|
||||||
//[self.sizingNode setNeedsLayout];
|
//[self.sizingNode setNeedsLayout];
|
||||||
self.sizingNode.frame = CGRectMake((self.view.bounds.size.width - size.width) / 2.0,
|
self.sizingNode.frame = CGRectMake((CGRectGetWidth(bounds) - size.width) / 2.0,
|
||||||
(self.view.bounds.size.height - size.height) / 2.0,
|
(CGRectGetHeight(bounds) - size.height) / 2.0,
|
||||||
size.width, size.height);
|
size.width,
|
||||||
|
size.height);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,10 +8,27 @@
|
|||||||
|
|
||||||
#import "SampleSizingNode.h"
|
#import "SampleSizingNode.h"
|
||||||
|
|
||||||
|
@interface SampleSizingNodeSubnode : ASDisplayNode
|
||||||
|
@property (strong, nonatomic) ASTextNode *textNode;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation SampleSizingNodeSubnode
|
||||||
|
|
||||||
|
- (void)layout
|
||||||
|
{
|
||||||
|
[super layout];
|
||||||
|
|
||||||
|
// Manual layout after the normal layout engine did it's job
|
||||||
|
// Calculated size can be used after the layout spec pass happened
|
||||||
|
//self.textNode.frame = CGRectMake(self.textNode.frame.origin.x, self.textNode.frame.origin.y, self.textNode.calculatedSize.width, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@interface SampleSizingNode ()
|
@interface SampleSizingNode ()
|
||||||
@property (nonatomic, strong) ASDisplayNode *subnode;
|
|
||||||
@property (nonatomic, assign) NSInteger state;
|
@property (nonatomic, assign) NSInteger state;
|
||||||
|
|
||||||
|
@property (nonatomic, strong) SampleSizingNodeSubnode *subnode;
|
||||||
@property (nonatomic, strong) ASTextNode *textNode;
|
@property (nonatomic, strong) ASTextNode *textNode;
|
||||||
@property (nonatomic, strong) ASNetworkImageNode *imageNode;
|
@property (nonatomic, strong) ASNetworkImageNode *imageNode;
|
||||||
@end
|
@end
|
||||||
@ -35,13 +52,15 @@
|
|||||||
_imageNode.backgroundColor = [UIColor brownColor];
|
_imageNode.backgroundColor = [UIColor brownColor];
|
||||||
_imageNode.needsDisplayOnBoundsChange = YES;
|
_imageNode.needsDisplayOnBoundsChange = YES;
|
||||||
_imageNode.style.height = ASDimensionMakeWithFraction(1.0);
|
_imageNode.style.height = ASDimensionMakeWithFraction(1.0);
|
||||||
_imageNode.style.width = ASDimensionMake(30.0);
|
_imageNode.style.width = ASDimensionMake(50.0);
|
||||||
|
|
||||||
|
|
||||||
_subnode = [ASDisplayNode new];
|
_subnode = [SampleSizingNodeSubnode new];
|
||||||
|
_subnode.textNode = _textNode;
|
||||||
_subnode.backgroundColor = [UIColor redColor];
|
_subnode.backgroundColor = [UIColor redColor];
|
||||||
_subnode.automaticallyManagesSubnodes = YES;
|
_subnode.automaticallyManagesSubnodes = YES;
|
||||||
|
|
||||||
|
// Layout description via layoutSpecBlock
|
||||||
__weak __typeof(self) weakSelf = self;
|
__weak __typeof(self) weakSelf = self;
|
||||||
_subnode.layoutSpecBlock = ^ASLayoutSpec *(__kindof ASDisplayNode * _Nonnull node, ASSizeRange constrainedSize) {
|
_subnode.layoutSpecBlock = ^ASLayoutSpec *(__kindof ASDisplayNode * _Nonnull node, ASSizeRange constrainedSize) {
|
||||||
|
|
||||||
@ -113,7 +132,6 @@
|
|||||||
[self invalidateSize];
|
[self invalidateSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - ASDisplayNode
|
#pragma mark - ASDisplayNode
|
||||||
|
|
||||||
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||||
@ -129,5 +147,13 @@
|
|||||||
child:self.subnode];
|
child:self.subnode];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)layout
|
||||||
|
{
|
||||||
|
[super layout];
|
||||||
|
|
||||||
|
// Layout after the official layout pass happened
|
||||||
|
//self.subnode.frame = CGRectMake(self.subnode.frame.origin.x, self.subnode.frame.origin.y, 100, self.calculatedSize.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@ -201,7 +201,7 @@ static const CGFloat kInnerPadding = 10.0f;
|
|||||||
- (void)toggleImageEnlargement
|
- (void)toggleImageEnlargement
|
||||||
{
|
{
|
||||||
_isImageEnlarged = !_isImageEnlarged;
|
_isImageEnlarged = !_isImageEnlarged;
|
||||||
[self setNeedsLayout];
|
[self invalidateSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)toggleNodesSwap
|
- (void)toggleNodesSwap
|
||||||
@ -211,7 +211,7 @@ static const CGFloat kInnerPadding = 10.0f;
|
|||||||
[UIView animateWithDuration:0.15 animations:^{
|
[UIView animateWithDuration:0.15 animations:^{
|
||||||
self.alpha = 0;
|
self.alpha = 0;
|
||||||
} completion:^(BOOL finished) {
|
} completion:^(BOOL finished) {
|
||||||
[self setNeedsLayout];
|
[self invalidateSize];
|
||||||
[self.view layoutIfNeeded];
|
[self.view layoutIfNeeded];
|
||||||
|
|
||||||
[UIView animateWithDuration:0.15 animations:^{
|
[UIView animateWithDuration:0.15 animations:^{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user