add RATreeView as source
This commit is contained in:
@@ -0,0 +1,301 @@
|
||||
|
||||
//The MIT License (MIT)
|
||||
//
|
||||
//Copyright (c) 2014 Rafał Augustyniak
|
||||
//
|
||||
//Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
//this software and associated documentation files (the "Software"), to deal in
|
||||
//the Software without restriction, including without limitation the rights to
|
||||
//use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
//the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
//subject to the following conditions:
|
||||
//
|
||||
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
//FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
//COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
//IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
//CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#import "RATreeNodeCollectionController.h"
|
||||
#import "RATreeNodeController.h"
|
||||
|
||||
#import "RATreeNode.h"
|
||||
#import "RATreeNodeItem+Private.h"
|
||||
|
||||
#import "RABatchChanges.h"
|
||||
|
||||
|
||||
@interface RATreeNodeCollectionController () <RATreeNodeItemDataSource>
|
||||
|
||||
@property (nonatomic, strong) RATreeNodeController *rootController;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation RATreeNodeCollectionController
|
||||
|
||||
- (NSInteger)numberOfVisibleRowsForItems
|
||||
{
|
||||
return self.rootController.numberOfVisibleDescendants;
|
||||
}
|
||||
|
||||
- (RATreeNode *)treeNodeForIndex:(NSInteger)index
|
||||
{
|
||||
return [self.rootController controllerForIndex:index].treeNode;
|
||||
}
|
||||
|
||||
- (NSInteger)indexForItem:(id)item
|
||||
{
|
||||
return [self.rootController indexForItem:item];
|
||||
}
|
||||
|
||||
- (NSInteger)lastVisibleDescendantIndexForItem:(id)item
|
||||
{
|
||||
return [self.rootController lastVisibleDescendatIndexForItem:item];
|
||||
}
|
||||
|
||||
- (id)parentForItem:(id)item
|
||||
{
|
||||
RATreeNodeController *controller = [self.rootController controllerForItem:item];
|
||||
return controller.parentController.treeNode.item;
|
||||
}
|
||||
|
||||
- (NSInteger)levelForItem:(id)item
|
||||
{
|
||||
return [self.rootController controllerForItem:item].level;
|
||||
}
|
||||
|
||||
- (id)childInParent:(id)parent atIndex:(NSInteger)index
|
||||
{
|
||||
RATreeNodeController *controller = [self.rootController controllerForItem:parent].childControllers[index];
|
||||
return controller.treeNode.item;
|
||||
}
|
||||
|
||||
- (void)expandRowForItem:(id)item updates:(void (^)(NSIndexSet *))updates
|
||||
{
|
||||
[self expandRowForItem:item expandChildren:YES updates:updates];
|
||||
}
|
||||
|
||||
- (void)expandRowForItem:(id)item expandChildren:(BOOL)expandChildren updates:(void (^)(NSIndexSet *))updates
|
||||
{
|
||||
NSParameterAssert(updates);
|
||||
|
||||
RATreeNodeController *parentController = [self.rootController controllerForItem:item];
|
||||
NSMutableArray *items = [@[item] mutableCopy];
|
||||
|
||||
while ([items count] > 0) {
|
||||
id currentItem = [items firstObject];
|
||||
[items removeObject:currentItem];
|
||||
|
||||
RATreeNodeController *controller = [self.rootController controllerForItem:currentItem];
|
||||
NSMutableArray *oldChildItems = [NSMutableArray array];
|
||||
for (RATreeNodeController *nodeController in controller.childControllers) {
|
||||
[oldChildItems addObject:nodeController.treeNode.item];
|
||||
}
|
||||
|
||||
NSInteger numberOfChildren = [self.dataSource treeNodeCollectionController:self numberOfChildrenForItem:controller.treeNode.item];
|
||||
NSIndexSet *allIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, numberOfChildren)];
|
||||
|
||||
NSArray *currentChildControllersAndIndexes = [self controllersAndIndexesForNodesWithIndexes:allIndexes inParentController:controller];
|
||||
NSArray *currentChildControllers = [currentChildControllersAndIndexes valueForKey:@"controller"];
|
||||
|
||||
NSMutableArray *childControllersToInsert = [NSMutableArray array];
|
||||
NSMutableIndexSet *indexesForInsertions = [NSMutableIndexSet indexSet];
|
||||
NSMutableArray *childControllersToRemove = [NSMutableArray array];
|
||||
NSMutableIndexSet *indexesForDeletions = [NSMutableIndexSet indexSet];
|
||||
|
||||
for (RATreeNodeController *loopNodeController in currentChildControllers) {
|
||||
if (![controller.childControllers containsObject:loopNodeController]
|
||||
&& ![oldChildItems containsObject:controller.treeNode.item]) {
|
||||
[childControllersToInsert addObject:loopNodeController];
|
||||
NSInteger index = [currentChildControllers indexOfObject:loopNodeController];
|
||||
NSAssert(index != NSNotFound, nil);
|
||||
[indexesForInsertions addIndex:index];
|
||||
}
|
||||
}
|
||||
|
||||
for (RATreeNodeController *loopNodeController in controller.childControllers) {
|
||||
if (![currentChildControllers containsObject:loopNodeController]
|
||||
&& ![childControllersToInsert containsObject:loopNodeController]) {
|
||||
[childControllersToRemove addObject:loopNodeController];
|
||||
NSInteger index = [controller.childControllers indexOfObject:loopNodeController];
|
||||
NSAssert(index != NSNotFound, nil);
|
||||
[indexesForDeletions addIndex:index];
|
||||
}
|
||||
}
|
||||
|
||||
[controller removeChildControllersAtIndexes:indexesForDeletions];
|
||||
[controller insertChildControllers:childControllersToInsert atIndexes:indexesForInsertions];
|
||||
|
||||
if (expandChildren) {
|
||||
for (RATreeNodeController *nodeController in controller.childControllers) {
|
||||
[items addObject:nodeController.treeNode.item];
|
||||
}
|
||||
}
|
||||
|
||||
[controller expandAndExpandChildren:expandChildren];
|
||||
}
|
||||
|
||||
updates(parentController.descendantsIndexes);
|
||||
}
|
||||
|
||||
- (void)collapseRowForItem:(id)item collapseChildren:(BOOL)collapseChildren updates:(void (^)(NSIndexSet *))updates
|
||||
{
|
||||
NSParameterAssert(updates);
|
||||
|
||||
RATreeNodeController *controller = [self.rootController controllerForItem:item];
|
||||
NSIndexSet *deletions = controller.descendantsIndexes;
|
||||
[controller collapseAndCollapseChildren:collapseChildren];
|
||||
|
||||
updates(deletions);
|
||||
}
|
||||
|
||||
- (void)insertItemsAtIndexes:(NSIndexSet *)indexes inParent:(id)item
|
||||
{
|
||||
RATreeNodeController *parentController = [self.rootController controllerForItem:item];
|
||||
NSArray *newControllers = [self controllersForNodesWithIndexes:indexes inParentController:parentController];
|
||||
[parentController insertChildControllers:newControllers atIndexes:indexes];
|
||||
}
|
||||
|
||||
- (void)moveItemAtIndex:(NSInteger)index inParent:(id)parent toIndex:(NSInteger)newIndex inParent:(id)newParent updates:(void (^)(NSIndexSet *, NSIndexSet *))updates
|
||||
{
|
||||
NSParameterAssert(updates);
|
||||
|
||||
NSMutableIndexSet *removedIndexes = [NSMutableIndexSet indexSet];
|
||||
NSMutableIndexSet *addedIndexes = [NSMutableIndexSet indexSet];
|
||||
|
||||
RATreeNodeController *parentController = [self.rootController controllerForItem:parent];
|
||||
|
||||
if (parent == newParent) {
|
||||
[parentController moveChildControllerAtIndex:index toIndex:newIndex];
|
||||
|
||||
} else {
|
||||
RATreeNodeController *childController = parentController.childControllers[index];
|
||||
|
||||
[removedIndexes addIndex:childController.index];
|
||||
[removedIndexes addIndexes:childController.descendantsIndexes];
|
||||
|
||||
RATreeNodeController *newParentController = [self.rootController controllerForItem:parent];
|
||||
[parentController removeChildControllersAtIndexes:[NSIndexSet indexSetWithIndex:index]];
|
||||
[newParentController insertChildControllers:@[childController] atIndexes:[NSIndexSet indexSetWithIndex:newIndex]];
|
||||
|
||||
[addedIndexes addIndex:childController.index];
|
||||
[addedIndexes addIndexes:childController.descendantsIndexes];
|
||||
}
|
||||
|
||||
updates(removedIndexes, addedIndexes);
|
||||
}
|
||||
|
||||
- (void)removeItemsAtIndexes:(NSIndexSet *)indexes inParent:(id)item updates:(void (^)(NSIndexSet *))updates
|
||||
{
|
||||
RATreeNodeController *parentController = [self.rootController controllerForItem:item];
|
||||
|
||||
NSMutableIndexSet *indexesToRemoval = [NSMutableIndexSet indexSet];
|
||||
[indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
|
||||
RATreeNodeController *controller = parentController.childControllers[idx];
|
||||
[indexesToRemoval addIndex:controller.index];
|
||||
[indexesToRemoval addIndexes:controller.descendantsIndexes];
|
||||
}];
|
||||
|
||||
[parentController removeChildControllersAtIndexes:indexes];
|
||||
|
||||
updates(indexesToRemoval);
|
||||
}
|
||||
|
||||
- (NSArray *)controllersAndIndexesForNodesWithIndexes:(NSIndexSet *)indexes inParentController:(RATreeNodeController *)parentController
|
||||
{
|
||||
NSMutableArray *childControllers = [parentController.childControllers mutableCopy];
|
||||
NSMutableArray *currentControllers = [NSMutableArray array];
|
||||
|
||||
NSMutableArray *invalidItems = [NSMutableArray array];
|
||||
for (RATreeNodeController *nodeController in parentController.childControllers) {
|
||||
[invalidItems addObject:nodeController.treeNode.item];
|
||||
}
|
||||
|
||||
[indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
|
||||
|
||||
RATreeNodeController *controller;
|
||||
RATreeNodeController *oldControllerForCurrentIndex = nil;
|
||||
|
||||
|
||||
RATreeNodeItem *lazyItem = [[RATreeNodeItem alloc] initWithParent:parentController.treeNode.item index:idx];
|
||||
lazyItem.dataSource = self;
|
||||
|
||||
|
||||
for (RATreeNodeController *controller in parentController.childControllers) {
|
||||
if ([controller.treeNode.item isEqual:lazyItem.item]) {
|
||||
oldControllerForCurrentIndex = controller;
|
||||
}
|
||||
}
|
||||
if (oldControllerForCurrentIndex != nil) {
|
||||
controller = oldControllerForCurrentIndex;
|
||||
|
||||
} else {
|
||||
controller = [[RATreeNodeController alloc] initWithParent:parentController item:lazyItem expandedBlock:^BOOL(id item) {
|
||||
return [childControllers indexOfObjectPassingTest:^BOOL(RATreeNodeController *controller, NSUInteger idx, BOOL *stop) {
|
||||
return [controller.treeNode.item isEqual:item];
|
||||
}] != NSNotFound;
|
||||
}];
|
||||
}
|
||||
|
||||
[currentControllers addObject:@{ @"index" : @(idx),
|
||||
@"controller" : controller }];
|
||||
}];
|
||||
|
||||
return [currentControllers copy];
|
||||
}
|
||||
|
||||
- (NSArray *)controllersForNodesWithIndexes:(NSIndexSet *)indexes inParentController:(RATreeNodeController *)parentController
|
||||
{
|
||||
return [[self controllersAndIndexesForNodesWithIndexes:indexes inParentController:parentController] valueForKey:@"controller"];
|
||||
}
|
||||
|
||||
- (NSArray *)controllersForNodes:(NSInteger)nodesNumber inParentController:(RATreeNodeController *)parentController
|
||||
{
|
||||
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, nodesNumber)];
|
||||
return [self controllersForNodesWithIndexes:indexSet inParentController:parentController];
|
||||
}
|
||||
|
||||
#pragma mark - RATreeNodeController delegate
|
||||
|
||||
- (id)treeNodeController:(RATreeNodeController *)controller child:(NSInteger)childIndex
|
||||
{
|
||||
return [self.dataSource treeNodeCollectionController:self child:childIndex ofItem:controller.treeNode.item];
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfChildrenForTreeNodeController:(RATreeNodeController *)controller
|
||||
{
|
||||
return [self.dataSource treeNodeCollectionController:self numberOfChildrenForItem:controller.treeNode.item];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - RATreeNodeItem data source
|
||||
|
||||
- (id)itemForTreeNodeItem:(RATreeNodeItem *)treeNodeItem
|
||||
{
|
||||
return [self.dataSource treeNodeCollectionController:self child:treeNodeItem.index ofItem:treeNodeItem.parent];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (RATreeNodeController *)rootController
|
||||
{
|
||||
if (!_rootController) {
|
||||
_rootController = [[RATreeNodeController alloc] initWithParent:nil item:nil expandedBlock:^BOOL(id _) {
|
||||
return YES;
|
||||
}];
|
||||
|
||||
NSInteger numberOfChildren = [self.dataSource treeNodeCollectionController:self numberOfChildrenForItem:nil];
|
||||
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, numberOfChildren)];
|
||||
NSArray *childControllers = [self controllersForNodesWithIndexes:indexSet inParentController:_rootController];
|
||||
[_rootController insertChildControllers:childControllers atIndexes:indexSet];
|
||||
}
|
||||
|
||||
return _rootController;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user