/* HBTreeNode.m $
This file is part of the HandBrake source code.
Homepage: .
It may be used under the terms of the GNU General Public License. */
#import "HBTreeNode.h"
@implementation HBTreeNode
- (instancetype)init
{
self = [super init];
if (self) {
_children = [[NSMutableArray alloc] init];
_isLeaf = YES;
}
return self;
}
- (id)copyWithZone:(NSZone *)zone
{
HBTreeNode *node = [[self class] allocWithZone:zone];
node->_children = [[NSMutableArray alloc] init];
node->_isLeaf = self.isLeaf;
for (HBTreeNode *children in self.children)
{
[node.children addObject:[children copy]];
}
return node;
}
- (void)setDelegate:(id)delegate
{
_delegate = delegate;
for (HBTreeNode *node in self.children)
{
node.delegate = delegate;
}
}
- (NSUInteger)countOfChildren
{
return self.children.count;
}
- (id)objectInChildrenAtIndex:(NSUInteger)index
{
return self.children[index];
}
- (void)insertObject:(HBTreeNode *)object inChildrenAtIndex:(NSUInteger)index
{
[self.children insertObject:object atIndex:index];
object.delegate = self.delegate;
[self.delegate nodeDidChange:self];
}
- (void)removeObjectFromChildrenAtIndex:(NSUInteger)index
{
self.children[index].delegate = nil;
[self.children removeObjectAtIndex:index];
[self.delegate nodeDidChange:self];
}
- (void)replaceObjectInChildrenAtIndex:(NSUInteger)index withObject:(HBTreeNode *)object
{
[self.children replaceObjectAtIndex:index withObject:object];
object.delegate = self.delegate;
[self.delegate nodeDidChange:self];
}
#pragma mark - Enumeration
- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSIndexPath *idx, BOOL *stop))block
{
BOOL stop = NO;
NSMutableArray *queue = [[NSMutableArray alloc] init];
NSMutableArray *indexesQueue = [[NSMutableArray alloc] init];
[queue addObject:self];
[indexesQueue addObject:[[NSIndexPath alloc] init]];
HBTreeNode *node = nil;
while ((node = [queue lastObject]) != nil)
{
// Get the index path of the current object
NSIndexPath *indexPath = [indexesQueue lastObject];
// Call the block
block(node, indexPath, &stop);
if (stop)
{
break;
}
[indexesQueue removeLastObject];
for (NSInteger i = node.children.count - 1; i >= 0; i--)
{
[indexesQueue addObject:[indexPath indexPathByAddingIndex:i]];
}
[queue removeLastObject];
for (id childNode in [node.children reverseObjectEnumerator])
{
[queue addObject:childNode];
}
}
}
- (NSIndexPath *)indexPathOfObject:(id)obj
{
__block NSIndexPath *retValue = nil;
// Visit the whole tree to find the index path.
[self enumerateObjectsUsingBlock:^(id obj2, NSIndexPath *idx, BOOL *stop)
{
if ([obj2 isEqualTo:obj])
{
retValue = idx;
*stop = YES;
}
}];
return retValue;
}
- (void)removeObjectAtIndexPath:(NSIndexPath *)idx
{
HBTreeNode *parentNode = self;
// Find the object parent array
// and delete it.
NSUInteger currIdx = 0;
NSUInteger i = 0;
for (i = 0; i < idx.length - 1; i++)
{
currIdx = [idx indexAtPosition:i];
if (parentNode.children.count > currIdx)
{
parentNode = parentNode.children[currIdx];
}
}
currIdx = [idx indexAtPosition:i];
if (parentNode.children.count > currIdx)
{
id removedNode = parentNode.children[currIdx];
[parentNode removeObjectFromChildrenAtIndex:currIdx];
if ([self.delegate respondsToSelector:@selector(treeDidRemoveNode:)])
{
[self.delegate treeDidRemoveNode:removedNode];
}
}
}
- (void)replaceObjectAtIndexPath:(NSIndexPath *)idx withObject:(HBTreeNode *)object
{
HBTreeNode *parentNode = self;
// Find the object parent array
NSUInteger currIdx = 0;
NSUInteger i = 0;
for (i = 0; i < idx.length - 1; i++)
{
currIdx = [idx indexAtPosition:i];
if (parentNode.children.count > currIdx)
{
parentNode = parentNode.children[currIdx];
}
}
NSUInteger insertionIndex = [idx indexAtPosition:idx.length - 1];
[parentNode replaceObjectInChildrenAtIndex:insertionIndex withObject:object];
}
@end