mirror of
https://github.com/wu736139669/Ash_AWord.git
synced 2026-08-08 06:46:38 +00:00
194 lines
7.5 KiB
Objective-C
194 lines
7.5 KiB
Objective-C
//
|
|
// PSTGridLayoutRow.m
|
|
// PSPDFKit
|
|
//
|
|
// Copyright (c) 2012-2013 Peter Steinberger. All rights reserved.
|
|
//
|
|
|
|
#import "PSTCollectionView.h"
|
|
#import "PSTGridLayoutRow.h"
|
|
#import "PSTGridLayoutSection.h"
|
|
#import "PSTGridLayoutItem.h"
|
|
#import "PSTGridLayoutInfo.h"
|
|
|
|
@interface PSTGridLayoutRow () {
|
|
NSMutableArray *_items;
|
|
BOOL _isValid;
|
|
int _verticalAlignement;
|
|
int _horizontalAlignement;
|
|
}
|
|
@property (nonatomic, strong) NSArray *items;
|
|
@end
|
|
|
|
@implementation PSTGridLayoutRow
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark - NSObject
|
|
|
|
- (id)init {
|
|
if ((self = [super init])) {
|
|
_items = [NSMutableArray new];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (NSString *)description {
|
|
return [NSString stringWithFormat:@"<%@: %p frame:%@ index:%ld items:%@>", NSStringFromClass(self.class), self, NSStringFromCGRect(self.rowFrame), (long)self.index, self.items];
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark - Public
|
|
|
|
- (void)invalidate {
|
|
_isValid = NO;
|
|
_rowSize = CGSizeZero;
|
|
_rowFrame = CGRectZero;
|
|
}
|
|
|
|
- (NSArray *)itemRects {
|
|
return [self layoutRowAndGenerateRectArray:YES];
|
|
}
|
|
|
|
- (void)layoutRow {
|
|
[self layoutRowAndGenerateRectArray:NO];
|
|
}
|
|
|
|
- (NSArray *)layoutRowAndGenerateRectArray:(BOOL)generateRectArray {
|
|
NSMutableArray *rects = generateRectArray ? [NSMutableArray array] : nil;
|
|
if (!_isValid || generateRectArray) {
|
|
// properties for aligning
|
|
BOOL isHorizontal = self.section.layoutInfo.horizontal;
|
|
BOOL isLastRow = self.section.indexOfImcompleteRow == self.index;
|
|
PSTFlowLayoutHorizontalAlignment horizontalAlignment = [self.section.rowAlignmentOptions[isLastRow ? PSTFlowLayoutLastRowHorizontalAlignmentKey : PSTFlowLayoutCommonRowHorizontalAlignmentKey] integerValue];
|
|
|
|
// calculate space that's left over if we would align it from left to right.
|
|
CGFloat leftOverSpace = self.section.layoutInfo.dimension;
|
|
if (isHorizontal) {
|
|
leftOverSpace -= self.section.sectionMargins.top + self.section.sectionMargins.bottom;
|
|
}else {
|
|
leftOverSpace -= self.section.sectionMargins.left + self.section.sectionMargins.right;
|
|
}
|
|
|
|
// calculate the space that we have left after counting all items.
|
|
// UICollectionView is smart and lays out items like they would have been placed on a full row
|
|
// So we need to calculate the "usedItemCount" with using the last item as a reference size.
|
|
// This allows us to correctly justify-place the items in the grid.
|
|
NSInteger usedItemCount = 0;
|
|
NSInteger itemIndex = 0;
|
|
CGFloat spacing = isHorizontal ? self.section.verticalInterstice : self.section.horizontalInterstice;
|
|
// the last row should justify as if it is filled with more (invisible) items so that the whole
|
|
// UICollectionView feels more like a grid than a random line of blocks
|
|
while (itemIndex < self.itemCount || isLastRow) {
|
|
CGFloat nextItemSize;
|
|
// first we need to find the size (width/height) of the next item to fit
|
|
if (!self.fixedItemSize) {
|
|
PSTGridLayoutItem *item = self.items[(NSUInteger)MIN(itemIndex, self.itemCount - 1)];
|
|
nextItemSize = isHorizontal ? item.itemFrame.size.height : item.itemFrame.size.width;
|
|
}else {
|
|
nextItemSize = isHorizontal ? self.section.itemSize.height : self.section.itemSize.width;
|
|
}
|
|
|
|
// the first item does not add a separator spacing,
|
|
// every one afterwards in the same row will need this spacing constant
|
|
if (itemIndex > 0) {
|
|
nextItemSize += spacing;
|
|
}
|
|
|
|
// check to see if we can at least fit an item (+separator if necessary)
|
|
if (leftOverSpace < nextItemSize) {
|
|
break;
|
|
}
|
|
|
|
// we need to maintain the leftover space after the maximum amount of items have
|
|
// occupied, so we know how to adjust equal spacing among all the items in a row
|
|
leftOverSpace -= nextItemSize;
|
|
|
|
itemIndex++;
|
|
usedItemCount = itemIndex;
|
|
}
|
|
|
|
// push everything to the right if right-aligning and divide in half for centered
|
|
// currently there is no public API supporting this behavior
|
|
CGPoint itemOffset = CGPointZero;
|
|
if (horizontalAlignment == PSTFlowLayoutHorizontalAlignmentRight) {
|
|
itemOffset.x += leftOverSpace;
|
|
}else if (horizontalAlignment == PSTFlowLayoutHorizontalAlignmentCentered ||
|
|
(horizontalAlignment == PSTFlowLayoutHorizontalAlignmentJustify && usedItemCount == 1)) {
|
|
// Special case one item row to split leftover space in half
|
|
itemOffset.x += leftOverSpace / 2;
|
|
}
|
|
|
|
// calculate the justified spacing among all items in a row if we are using
|
|
// the default PSTFlowLayoutHorizontalAlignmentJustify layout
|
|
CGFloat interSpacing = usedItemCount <= 1 ? 0 : leftOverSpace / (CGFloat)(usedItemCount - 1);
|
|
|
|
// calculate row frame as union of all items
|
|
CGRect frame = CGRectZero;
|
|
CGRect itemFrame = (CGRect){.size=self.section.itemSize};
|
|
for (itemIndex = 0; itemIndex < self.itemCount; itemIndex++) {
|
|
PSTGridLayoutItem *item = nil;
|
|
if (!self.fixedItemSize) {
|
|
item = self.items[(NSUInteger)itemIndex];
|
|
itemFrame = [item itemFrame];
|
|
}
|
|
// depending on horizontal/vertical for an item size (height/width),
|
|
// we add the minimum separator then an equally distributed spacing
|
|
// (since our default mode is justify) calculated from the total leftover
|
|
// space divided by the number of intervals
|
|
if (isHorizontal) {
|
|
itemFrame.origin.y = itemOffset.y;
|
|
itemOffset.y += itemFrame.size.height + self.section.verticalInterstice;
|
|
if (horizontalAlignment == PSTFlowLayoutHorizontalAlignmentJustify) {
|
|
itemOffset.y += interSpacing;
|
|
}
|
|
}else {
|
|
itemFrame.origin.x = itemOffset.x;
|
|
itemOffset.x += itemFrame.size.width + self.section.horizontalInterstice;
|
|
if (horizontalAlignment == PSTFlowLayoutHorizontalAlignmentJustify) {
|
|
itemOffset.x += interSpacing;
|
|
}
|
|
}
|
|
item.itemFrame = itemFrame; // might call nil; don't care
|
|
[rects addObject:[NSValue valueWithCGRect:itemFrame]];
|
|
frame = CGRectUnion(frame, itemFrame);
|
|
}
|
|
_rowSize = frame.size;
|
|
// _rowFrame = frame; // set externally
|
|
_isValid = YES;
|
|
}
|
|
return rects;
|
|
}
|
|
|
|
- (void)addItem:(PSTGridLayoutItem *)item {
|
|
[_items addObject:item];
|
|
item.rowObject = self;
|
|
[self invalidate];
|
|
}
|
|
|
|
- (PSTGridLayoutRow *)snapshot {
|
|
PSTGridLayoutRow *snapshotRow = [self.class new];
|
|
snapshotRow.section = self.section;
|
|
snapshotRow.items = self.items;
|
|
snapshotRow.rowSize = self.rowSize;
|
|
snapshotRow.rowFrame = self.rowFrame;
|
|
snapshotRow.index = self.index;
|
|
snapshotRow.complete = self.complete;
|
|
snapshotRow.fixedItemSize = self.fixedItemSize;
|
|
snapshotRow.itemCount = self.itemCount;
|
|
return snapshotRow;
|
|
}
|
|
|
|
- (PSTGridLayoutRow *)copyFromSection:(PSTGridLayoutSection *)section {
|
|
return nil; // ???
|
|
}
|
|
|
|
- (NSInteger)itemCount {
|
|
if (self.fixedItemSize) {
|
|
return _itemCount;
|
|
}else {
|
|
return (NSInteger)self.items.count;
|
|
}
|
|
}
|
|
|
|
@end
|