1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-12 09:29:55 +01:00
Telegram/Telegraph/TGCollectionMenuController.m

513 lines
18 KiB
Mathematica
Raw Normal View History

2014-07-10 16:11:09 +02:00
#import "TGCollectionMenuController.h"
#import "TGInterfaceAssets.h"
#import "TGImageUtils.h"
#import "TGCollectionMenuView.h"
#import "TGCollectionMenuLayout.h"
2015-10-01 18:19:52 +02:00
@interface TGCollectionMenuSection ()
- (void)insertItem:(TGCollectionItem *)item atIndex:(NSUInteger)index;
- (void)deleteItemAtIndex:(NSUInteger)index;
- (void)replaceItemAtIndex:(NSUInteger)index withItem:(TGCollectionItem *)item;
@end
@interface TGCollectionMenuController () <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, TGCollectionMenuViewDelegate, TGCollectionMenuLayoutDataSource, TGCollectionMenuLayoutDelegateFlowLayout>
2014-07-10 16:11:09 +02:00
{
bool _editingMode;
NSMutableSet *_collectionRegisteredIdentifiers;
CGFloat _currentLayoutWidth;
UIView *_headerBackgroundView;
}
@end
@implementation TGCollectionMenuController
- (id)init
{
self = [super init];
if (self)
{
_menuSections = [[TGCollectionMenuSectionList alloc] init];
}
return self;
}
- (void)dealloc
{
_collectionView.delegate = nil;
_collectionView.dataSource = nil;
}
- (void)enterEditingMode:(bool)animated
{
if (!_editingMode)
{
_editingMode = true;
[_collectionView setEditing:true animated:animated];
[self didEnterEditingMode:animated];
}
}
- (void)leaveEditingMode:(bool)animated
{
if (_editingMode)
{
_editingMode = false;
[_collectionView setEditing:false animated:animated];
[self didLeaveEditingMode:animated];
}
}
- (void)didEnterEditingMode:(bool)__unused animated
{
}
- (void)didLeaveEditingMode:(bool)__unused animated
{
}
- (void)_resetCollectionView
{
if (_collectionView != nil)
{
_collectionView.delegate = nil;
_collectionView.dataSource = nil;
[_collectionView removeFromSuperview];
}
_currentLayoutWidth = self.view.frame.size.width;
_collectionRegisteredIdentifiers = [[NSMutableSet alloc] init];
_collectionLayout = [[TGCollectionMenuLayout alloc] init];
_collectionView = [[TGCollectionMenuView alloc] initWithFrame:self.view.bounds collectionViewLayout:_collectionLayout];
_collectionView.backgroundColor = nil;
_collectionView.opaque = false;
_collectionView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_collectionView.dataSource = self;
_collectionView.delegate = self;
_collectionView.alwaysBounceVertical = true;
[_collectionView registerClass:[TGCollectionItemView class] forCellWithReuseIdentifier:@"_empty"];
2015-10-01 18:19:52 +02:00
__weak TGCollectionMenuController *weakSelf = self;
_collectionView.layoutForSize = ^(CGSize size) {
__strong TGCollectionMenuController *strongSelf = weakSelf;
if (strongSelf != nil) {
strongSelf->_currentLayoutWidth = size.width;
[strongSelf->_collectionLayout invalidateLayout];
[strongSelf->_collectionView setNeedsLayout];
[strongSelf->_collectionView layoutSubviews];
}
};
2014-07-10 16:11:09 +02:00
[self.view insertSubview:_collectionView aboveSubview:_headerBackgroundView];
}
- (void)collectionMenuViewDidEnterEditingMode:(TGCollectionMenuView *)__unused collectionMenuView
{
if (!_editingMode)
{
_editingMode = true;
[self didEnterEditingMode:true];
}
}
- (void)collectionMenuViewDidLeaveEditingMode:(TGCollectionMenuView *)__unused collectionMenuView
{
if (_editingMode)
{
_editingMode = false;
[self didLeaveEditingMode:true];
}
}
- (NSIndexPath *)indexPathForItem:(TGCollectionItem *)item
{
int sectionIndex = -1;
for (TGCollectionMenuSection *section in _menuSections.sections)
{
sectionIndex++;
int itemIndex = -1;
for (TGCollectionItem *listItem in section.items)
{
itemIndex++;
if (listItem == item)
{
return [NSIndexPath indexPathForItem:itemIndex inSection:sectionIndex];
}
}
}
return nil;
}
- (NSUInteger)indexForSection:(TGCollectionMenuSection *)section
{
int index = -1;
for (TGCollectionMenuSection *listSection in _menuSections.sections)
{
index++;
if (listSection == section)
return (NSUInteger)index;
}
return NSNotFound;
}
- (void)loadView
{
[super loadView];
2015-10-01 18:19:52 +02:00
if (TGIsPad()) {
self.view.frame = self.navigationController.view.bounds;
}
2014-07-10 16:11:09 +02:00
self.view.backgroundColor = [TGInterfaceAssets listsBackgroundColor];
_headerBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.view.frame.size.width, self.controllerInset.top)];
_headerBackgroundView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_headerBackgroundView];
[self _resetCollectionView];
[self setExplicitTableInset:UIEdgeInsetsMake(-(TGIsRetina() ? 0.5f : 1.0f), 0, 0, 0)];
if (![self _updateControllerInset:false])
[self controllerInsetUpdated:UIEdgeInsetsZero];
}
#pragma mark -
- (void)controllerInsetUpdated:(UIEdgeInsets)previousInset
{
[super controllerInsetUpdated:previousInset];
if ([self isViewLoaded])
_headerBackgroundView.frame = CGRectMake(0.0f, 0.0f, self.view.frame.size.width, self.controllerInset.top);
}
- (void)viewWillAppear:(BOOL)animated
{
for (NSIndexPath *indexPath in [_collectionView indexPathsForSelectedItems])
{
[_collectionView deselectItemAtIndexPath:indexPath animated:animated];
}
[super viewWillAppear:animated];
}
2015-10-01 18:19:52 +02:00
/*- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
2014-07-10 16:11:09 +02:00
{
2015-10-01 18:19:52 +02:00
CGFloat currentLayoutWidth = [self inPopover] ? self.view.frame.size.width : [TGViewController screenSizeForInterfaceOrientation:toInterfaceOrientation].width;
_currentLayoutWidth = currentLayoutWidth;
2014-07-10 16:11:09 +02:00
[_collectionLayout invalidateLayout];
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
2015-10-01 18:19:52 +02:00
}*/
2014-07-10 16:11:09 +02:00
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
if (collectionView == _collectionView)
return _menuSections.sections.count;
return 0;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
if (collectionView == _collectionView && section < (NSInteger)_menuSections.sections.count)
return ((TGCollectionMenuSection *)_menuSections.sections[section]).items.count;
return 0;
}
2015-10-01 18:19:52 +02:00
- (void)updateItem:(TGCollectionItem *)item itemView:(TGCollectionItemView *)itemView positionAtIndexPath:(NSIndexPath *)indexPath ignoreDragging:(bool)ignoreDragging animated:(bool)animated
{
TGCollectionItem *previousItem = nil;
if (indexPath.item > 0)
{
if (ignoreDragging || _collectionLayout.selectedItemIndexPath == nil || ![_collectionLayout.selectedItemIndexPath isEqual:[NSIndexPath indexPathForItem:indexPath.item - 1 inSection:indexPath.section]])
{
previousItem = ((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items[indexPath.item - 1];
}
}
TGCollectionItem *nextItem = nil;
if (indexPath.item < (NSInteger)((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items.count - 1)
{
if (ignoreDragging || _collectionLayout.selectedItemIndexPath == nil || ![_collectionLayout.selectedItemIndexPath isEqual:[NSIndexPath indexPathForItem:indexPath.item + 1 inSection:indexPath.section]])
{
nextItem = ((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items[indexPath.item + 1];
}
}
int itemPositionMask = 0;
if (!item.transparent)
{
if (previousItem == nil || previousItem.transparent)
itemPositionMask |= TGCollectionItemViewPositionFirstInBlock;
if (nextItem == nil || nextItem.transparent)
itemPositionMask |= TGCollectionItemViewPositionLastInBlock;
if (itemPositionMask == 0)
itemPositionMask = TGCollectionItemViewPositionMiddleInBlock;
}
[itemView setItemPosition:itemPositionMask animated:animated];
}
2014-07-10 16:11:09 +02:00
- (UICollectionViewCell *)collectionView:(TGCollectionMenuView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
TGCollectionItem *item = indexPath.section < (NSInteger)_menuSections.sections.count && indexPath.row < (NSInteger)((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items.count ? ((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items[indexPath.item] : nil;
if (item != nil)
{
TGCollectionItemView *itemView = [item dequeueItemView:collectionView registeredIdentifiers:_collectionRegisteredIdentifiers forIndexPath:indexPath];
if (itemView.boundItem != nil)
[itemView.boundItem unbindView];
2015-10-01 18:19:52 +02:00
[self updateItem:item itemView:itemView positionAtIndexPath:indexPath ignoreDragging:false animated:false];
2014-07-10 16:11:09 +02:00
[item bindView:itemView];
[collectionView setupCellForEditing:itemView];
return itemView;
}
return [collectionView dequeueReusableCellWithReuseIdentifier:@"_empty" forIndexPath:indexPath];
}
- (void)collectionView:(UICollectionView *)__unused collectionView didEndDisplayingCell:(TGCollectionItemView *)cell forItemAtIndexPath:(NSIndexPath *)__unused indexPath
{
[cell.boundItem unbindView];
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)__unused collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
TGCollectionItem *item = indexPath.section < (NSInteger)_menuSections.sections.count && indexPath.row < (NSInteger)((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items.count ? ((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items[indexPath.item] : nil;
CGSize layoutSize = collectionView.frame.size;
if (item != nil)
return [item itemSizeForContainerSize:layoutSize];
return CGSizeZero;
}
- (CGFloat)collectionView:(UICollectionView *)__unused collectionView layout:(UICollectionViewLayout *)__unused collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)__unused section
{
return 0.0f;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)__unused collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
if (collectionView == _collectionView)
{
return ((TGCollectionMenuSection *)_menuSections.sections[section]).insets;
}
return UIEdgeInsetsZero;
}
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
if (collectionView == _collectionView)
{
TGCollectionItem *item = indexPath.section < (NSInteger)_menuSections.sections.count && indexPath.row < (NSInteger)((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items.count ? ((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items[indexPath.item] : nil;
if (item != nil)
return item.highlightable;
}
return false;
}
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
if (collectionView == _collectionView)
{
TGCollectionItem *item = indexPath.section < (NSInteger)_menuSections.sections.count && indexPath.row < (NSInteger)((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items.count ? ((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items[indexPath.item] : nil;
if (item != nil)
return item.selectable;
}
return false;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
if (collectionView == _collectionView)
{
TGCollectionItem *item = indexPath.section < (NSInteger)_menuSections.sections.count && indexPath.row < (NSInteger)((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items.count ? ((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items[indexPath.item] : nil;
if (item != nil)
{
2015-10-01 18:19:52 +02:00
[item itemSelected:self];
2014-07-10 16:11:09 +02:00
if (item.deselectAutomatically)
[collectionView deselectItemAtIndexPath:indexPath animated:true];
}
}
}
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath
{
if (collectionView == _collectionView)
{
TGCollectionItem *item = indexPath.section < (NSInteger)_menuSections.sections.count && indexPath.row < (NSInteger)((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items.count ? ((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items[indexPath.item] : nil;
if (item != nil)
{
return [item itemWantsMenu];
}
}
return false;
}
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)__unused sender
{
if (collectionView == _collectionView)
{
TGCollectionItem *item = indexPath.section < (NSInteger)_menuSections.sections.count && indexPath.row < (NSInteger)((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items.count ? ((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items[indexPath.item] : nil;
if (item != nil)
{
return [item itemCanPerformAction:action];
}
}
return false;
}
- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)__unused sender
{
if (collectionView == _collectionView)
{
TGCollectionItem *item = indexPath.section < (NSInteger)_menuSections.sections.count && indexPath.row < (NSInteger)((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items.count ? ((TGCollectionMenuSection *)_menuSections.sections[indexPath.section]).items[indexPath.item] : nil;
if (item != nil)
{
return [item itemPerformAction:action];
}
}
}
2015-10-01 18:19:52 +02:00
- (void)collectionView:(UICollectionView *)__unused collectionView itemAtIndexPath:(NSIndexPath *)fromIndexPath willMoveToIndexPath:(NSIndexPath *)toIndexPath
{
TGCollectionMenuSection *fromSection = _menuSections.sections[fromIndexPath.section];
TGCollectionMenuSection *toSection = _menuSections.sections[toIndexPath.section];
if (fromSection == toSection)
{
NSInteger fromIndex = fromIndexPath.item;
id item = fromSection.items[fromIndex];
NSInteger toIndex = toIndexPath.item;
[fromSection deleteItemAtIndex:fromIndex];
[fromSection insertItem:item atIndex:toIndex];
}
else
{
id item = fromSection.items[fromIndexPath.item];
[fromSection deleteItemAtIndex:fromIndexPath.item];
[toSection insertItem:item atIndex:toIndexPath.item];
}
}
- (void)animateCollectionCrossfade
{
UIView *snapshotView = [self.collectionView snapshotViewAfterScreenUpdates:false];
[self.view insertSubview:snapshotView aboveSubview:self.collectionView];
[UIView animateWithDuration:0.3 animations:^
{
snapshotView.alpha = 0.0f;
} completion:^(__unused BOOL finished)
{
[snapshotView removeFromSuperview];
}];
}
- (void)updateItemPositions
{
[self updateItemPositions:false];
}
- (void)updateItemPositions:(bool)ignoreDragging
{
for (NSIndexPath *indexPath in [_collectionView indexPathsForVisibleItems])
{
TGCollectionMenuSection *section = _menuSections.sections[indexPath.section];
TGCollectionItem *item = section.items[indexPath.item];
TGCollectionItemView *itemView = (TGCollectionItemView *)[_collectionView cellForItemAtIndexPath:indexPath];
[self updateItem:item itemView:itemView positionAtIndexPath:indexPath ignoreDragging:ignoreDragging animated:true];
}
}
- (void)collectionView:(UICollectionView *)__unused collectionView itemAtIndexPath:(NSIndexPath *)__unused fromIndexPath willBeginMovingToIndexPath:(NSIndexPath *)__unused toIndexPath
{
[self updateItemPositions:false];
}
- (void)collectionView:(UICollectionView *)__unused collectionView layout:(UICollectionViewLayout *)__unused collectionViewLayout willEndDraggingItemAtIndexPath:(NSIndexPath *)__unused indexPath
{
[self updateItemPositions:true];
}
- (void)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)__unused collectionViewLayout willBeginDraggingItemAtIndexPath:(NSIndexPath *)indexPath
{
TGCollectionItemView *itemView = (TGCollectionItemView *)[collectionView cellForItemAtIndexPath:indexPath];
[itemView setItemPosition:TGCollectionItemViewPositionFirstInBlock | TGCollectionItemViewPositionLastInBlock];
}
- (void)collectionView:(UICollectionView *)__unused collectionView layout:(UICollectionViewLayout *)__unused collectionViewLayout didBeginDraggingItemAtIndexPath:(NSIndexPath *)__unused indexPath
{
[self updateItemPositions:false];
}
- (void)collectionView:(UICollectionView *)__unused collectionView itemAtIndexPath:(NSIndexPath *)__unused fromIndexPath didMoveToIndexPath:(NSIndexPath *)__unused toIndexPath
{
}
- (BOOL)collectionView:(UICollectionView *)__unused collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath
{
TGCollectionMenuSection *section = _menuSections.sections[indexPath.section];
TGCollectionItem *item = section.items[indexPath.item];
return _editingMode && item.canBeMovedToSectionAtIndex != nil;
}
- (BOOL)collectionView:(UICollectionView *)__unused collectionView itemAtIndexPath:(NSIndexPath *) fromIndexPath canMoveToIndexPath:(NSIndexPath *)toIndexPath
{
TGCollectionMenuSection *section = _menuSections.sections[fromIndexPath.section];
TGCollectionItem *item = section.items[fromIndexPath.item];
return item.canBeMovedToSectionAtIndex != nil && item.canBeMovedToSectionAtIndex(toIndexPath.section, toIndexPath.item);
}
- (BOOL)collectionViewCanMoveItems:(UICollectionView *)__unused collectionView
{
return _enableItemReorderingGestures;
}
2014-07-10 16:11:09 +02:00
@end