mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Add 'submodules/AsyncDisplayKit/' from commit '02bedc12816e251ad71777f9d2578329b6d2bef6'
git-subtree-dir: submodules/AsyncDisplayKit git-subtree-mainline:d06f423e0egit-subtree-split:02bedc1281
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
//
|
||||
// MosaicCollectionLayoutDelegate.m
|
||||
// Texture
|
||||
//
|
||||
// Copyright (c) Pinterest, Inc. All rights reserved.
|
||||
// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
|
||||
#import "MosaicCollectionLayoutDelegate.h"
|
||||
#import "MosaicCollectionLayoutInfo.h"
|
||||
#import "ImageCellNode.h"
|
||||
|
||||
#import <AsyncDisplayKit/ASCollectionElement.h>
|
||||
|
||||
@implementation MosaicCollectionLayoutDelegate {
|
||||
// Read-only properties
|
||||
MosaicCollectionLayoutInfo *_info;
|
||||
}
|
||||
|
||||
- (instancetype)initWithNumberOfColumns:(NSInteger)numberOfColumns headerHeight:(CGFloat)headerHeight
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_info = [[MosaicCollectionLayoutInfo alloc] initWithNumberOfColumns:numberOfColumns
|
||||
headerHeight:headerHeight
|
||||
columnSpacing:10.0
|
||||
sectionInsets:UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0)
|
||||
interItemSpacing:UIEdgeInsetsMake(10.0, 0, 10.0, 0)];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (ASScrollDirection)scrollableDirections
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
return ASScrollDirectionVerticalDirections;
|
||||
}
|
||||
|
||||
- (id)additionalInfoForLayoutWithElements:(ASElementMap *)elements
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
return _info;
|
||||
}
|
||||
|
||||
+ (ASCollectionLayoutState *)calculateLayoutWithContext:(ASCollectionLayoutContext *)context
|
||||
{
|
||||
CGFloat layoutWidth = context.viewportSize.width;
|
||||
ASElementMap *elements = context.elements;
|
||||
CGFloat top = 0;
|
||||
MosaicCollectionLayoutInfo *info = (MosaicCollectionLayoutInfo *)context.additionalInfo;
|
||||
|
||||
NSMapTable<ASCollectionElement *, UICollectionViewLayoutAttributes *> *attrsMap = [NSMapTable elementToLayoutAttributesTable];
|
||||
NSMutableArray *columnHeights = [NSMutableArray array];
|
||||
|
||||
NSInteger numberOfSections = [elements numberOfSections];
|
||||
for (NSUInteger section = 0; section < numberOfSections; section++) {
|
||||
NSInteger numberOfItems = [elements numberOfItemsInSection:section];
|
||||
|
||||
top += info.sectionInsets.top;
|
||||
|
||||
if (info.headerHeight > 0) {
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:section];
|
||||
ASCollectionElement *element = [elements supplementaryElementOfKind:UICollectionElementKindSectionHeader
|
||||
atIndexPath:indexPath];
|
||||
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader
|
||||
withIndexPath:indexPath];
|
||||
|
||||
ASSizeRange sizeRange = [self _sizeRangeForHeaderOfSection:section withLayoutWidth:layoutWidth info:info];
|
||||
CGSize size = [element.node layoutThatFits:sizeRange].size;
|
||||
CGRect frame = CGRectMake(info.sectionInsets.left, top, size.width, size.height);
|
||||
|
||||
attrs.frame = frame;
|
||||
[attrsMap setObject:attrs forKey:element];
|
||||
top = CGRectGetMaxY(frame);
|
||||
}
|
||||
|
||||
[columnHeights addObject:[NSMutableArray array]];
|
||||
for (NSUInteger idx = 0; idx < info.numberOfColumns; idx++) {
|
||||
[columnHeights[section] addObject:@(top)];
|
||||
}
|
||||
|
||||
CGFloat columnWidth = [self _columnWidthForSection:section withLayoutWidth:layoutWidth info:info];
|
||||
for (NSUInteger idx = 0; idx < numberOfItems; idx++) {
|
||||
NSUInteger columnIndex = [self _shortestColumnIndexInSection:section withColumnHeights:columnHeights];
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:idx inSection:section];
|
||||
ASCollectionElement *element = [elements elementForItemAtIndexPath:indexPath];
|
||||
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
|
||||
|
||||
ASSizeRange sizeRange = [self _sizeRangeForItem:element.node atIndexPath:indexPath withLayoutWidth:layoutWidth info:info];
|
||||
CGSize size = [element.node layoutThatFits:sizeRange].size;
|
||||
CGPoint position = CGPointMake(info.sectionInsets.left + (columnWidth + info.columnSpacing) * columnIndex,
|
||||
[columnHeights[section][columnIndex] floatValue]);
|
||||
CGRect frame = CGRectMake(position.x, position.y, size.width, size.height);
|
||||
|
||||
attrs.frame = frame;
|
||||
[attrsMap setObject:attrs forKey:element];
|
||||
// TODO Profile and avoid boxing if there are significant retain/release overheads
|
||||
columnHeights[section][columnIndex] = @(CGRectGetMaxY(frame) + info.interItemSpacing.bottom);
|
||||
}
|
||||
|
||||
NSUInteger columnIndex = [self _tallestColumnIndexInSection:section withColumnHeights:columnHeights];
|
||||
top = [columnHeights[section][columnIndex] floatValue] - info.interItemSpacing.bottom + info.sectionInsets.bottom;
|
||||
|
||||
for (NSUInteger idx = 0; idx < [columnHeights[section] count]; idx++) {
|
||||
columnHeights[section][idx] = @(top);
|
||||
}
|
||||
}
|
||||
|
||||
CGFloat contentHeight = [[[columnHeights lastObject] firstObject] floatValue];
|
||||
CGSize contentSize = CGSizeMake(layoutWidth, contentHeight);
|
||||
return [[ASCollectionLayoutState alloc] initWithContext:context
|
||||
contentSize:contentSize
|
||||
elementToLayoutAttributesTable:attrsMap];
|
||||
}
|
||||
|
||||
+ (CGFloat)_columnWidthForSection:(NSUInteger)section withLayoutWidth:(CGFloat)layoutWidth info:(MosaicCollectionLayoutInfo *)info
|
||||
{
|
||||
return ([self _widthForSection:section withLayoutWidth:layoutWidth info:info] - ((info.numberOfColumns - 1) * info.columnSpacing)) / info.numberOfColumns;
|
||||
}
|
||||
|
||||
+ (CGFloat)_widthForSection:(NSUInteger)section withLayoutWidth:(CGFloat)layoutWidth info:(MosaicCollectionLayoutInfo *)info
|
||||
{
|
||||
return layoutWidth - info.sectionInsets.left - info.sectionInsets.right;
|
||||
}
|
||||
|
||||
+ (ASSizeRange)_sizeRangeForItem:(ASCellNode *)item atIndexPath:(NSIndexPath *)indexPath withLayoutWidth:(CGFloat)layoutWidth info:(MosaicCollectionLayoutInfo *)info
|
||||
{
|
||||
CGFloat itemWidth = [self _columnWidthForSection:indexPath.section withLayoutWidth:layoutWidth info:info];
|
||||
if ([item isKindOfClass:[ImageCellNode class]]) {
|
||||
return ASSizeRangeMake(CGSizeMake(itemWidth, 0), CGSizeMake(itemWidth, CGFLOAT_MAX));
|
||||
} else {
|
||||
return ASSizeRangeMake(CGSizeMake(itemWidth, itemWidth)); // In kShowUICollectionViewCells = YES mode, make those cells itemWidth x itemWidth.
|
||||
}
|
||||
}
|
||||
|
||||
+ (ASSizeRange)_sizeRangeForHeaderOfSection:(NSInteger)section withLayoutWidth:(CGFloat)layoutWidth info:(MosaicCollectionLayoutInfo *)info
|
||||
{
|
||||
return ASSizeRangeMake(CGSizeMake(0, info.headerHeight), CGSizeMake([self _widthForSection:section withLayoutWidth:layoutWidth info:info], info.headerHeight));
|
||||
}
|
||||
|
||||
+ (NSUInteger)_tallestColumnIndexInSection:(NSUInteger)section withColumnHeights:(NSArray *)columnHeights
|
||||
{
|
||||
__block NSUInteger index = 0;
|
||||
__block CGFloat tallestHeight = 0;
|
||||
[columnHeights[section] enumerateObjectsUsingBlock:^(NSNumber *height, NSUInteger idx, BOOL *stop) {
|
||||
if (height.floatValue > tallestHeight) {
|
||||
index = idx;
|
||||
tallestHeight = height.floatValue;
|
||||
}
|
||||
}];
|
||||
return index;
|
||||
}
|
||||
|
||||
+ (NSUInteger)_shortestColumnIndexInSection:(NSUInteger)section withColumnHeights:(NSArray *)columnHeights
|
||||
{
|
||||
__block NSUInteger index = 0;
|
||||
__block CGFloat shortestHeight = CGFLOAT_MAX;
|
||||
[columnHeights[section] enumerateObjectsUsingBlock:^(NSNumber *height, NSUInteger idx, BOOL *stop) {
|
||||
if (height.floatValue < shortestHeight) {
|
||||
index = idx;
|
||||
shortestHeight = height.floatValue;
|
||||
}
|
||||
}];
|
||||
return index;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user