// Tue Nov 12 14:34:55 MET 1996 by Daniel Bðhringer


#import <misckit/misckit.h>
#import "MiscTree.TreeBrowser.h"

@interface Object(MiscTreeFeatures)
- linkBranchesWithParent;
- free;
@end

@implementation Matrix(SelExtension)
- scrollCellToVisible:aCell
{	int row,col;
	[self getRow:&row andCol:&col ofCell:aCell];
	return [self scrollCellToVisible:row:col];
}

@end

@implementation MiscTreeBrowser(NXBrowserCompat)
- setBrowserDelegate:aDelegate
{	if([aDelegate respondsTo:@selector(linkBranchesWithParent)])
		[aDelegate linkBranchesWithParent];
	return [self setRoot:aDelegate];
}
- setDelegate:aDelegate
{	return [self setBrowserDelegate:aDelegate];
}
- refineBackgroundColor
{	if(![window canStoreColor])
	{	[self setBackgroundColor:NX_COLORLTGRAY];
		[(Matrix*)cellMatrix setBackgroundColor:NX_COLORLTGRAY];
	}
	return self;
}

- cellNamed:(const char*)theName startingAt:(int) i;
{	List *cellList=[(Matrix*)cellMatrix cellList];
	Cell *currCell;
	for(; currCell=[cellList objectAt:i];i++)
	{	if(!strcmp([currCell stringValue],theName))
			return [(Matrix*)cellMatrix cellAt:i:0];
	} return nil;
}
- sendAction
{	//if([self target] && [self action]) [NXApp sendAction:[self action] to:[self target] from:self];
	return self;
}

#define pathSeparator "/"
- loadColumnZero {return self;}
- setPath:(const char *) search
{	int i;
	MiscString *str=[[MiscString alloc] initString:search],*currStr;
	List *elems=[str tokenize:pathSeparator into:nil];
	id		currCell=nil;
	BOOL	erg=YES;
	[self openCell:[(Matrix*)cellMatrix cellAt:0:0]];
	for(i=0;erg && (currStr=[elems objectAt:i]);i++)
	{	if(currCell=[self cellNamed:[currStr stringValue] startingAt:i])
			[self openCell:currCell];
		else erg=NO;
	} if(erg)
	{	[(Matrix*)cellMatrix selectCell:currCell];
		[(Matrix*)cellMatrix scrollCellToVisible:currCell];
	}
	[str free];[[elems freeObjects] free];
	return self;
}

@end

@implementation MiscTree(TreeBrowserDelegate) 

- (BOOL)canFree
{	return NO;
}

- parent {	return _parent;}

- setParent:(id<MiscTreeBrowserNodes>)aNode
{	if(_parent !=  aNode)
	{	_parent  = aNode;
		[_parent addChild:self];
	} return self;
}
// MiscTreeBrowserNodes methods

- (const char *)stringValue
{	return [self label];
}

- (unsigned int)childCount
{	return branches ? [branches count] : 0;
}

- childAt:(int)index
{	return branches ? [branches objectAt:index] : nil;
}

- (int)indexOfChild:(id<MiscTreeBrowserNodes>)aNode
{	return branches ? [branches indexOf:aNode] : NX_NOT_IN_LIST;
}

// MiscTreeBrowserEditing methods

- setStringValue:(const char *)aString
{	[label setStringValue:aString];
	return self;
}

// MiscTreeBrowserModifications methods

- createChildAfter:(id<MiscTreeBrowserNodes>)aNode
{	id kid = [[[self class] alloc] init];
	int index = [self indexOfChild:aNode];

	if ((index != NX_NOT_IN_LIST) && [self addChild:kid at:(index + 1)])
		return kid;
	else [kid free];
	return nil;
}

// only applicable for the root class
- createSibling
{	id pa = [self parent];

	return pa ? [pa createChildAfter:(id<MiscTreeBrowserNodes>)self] :
									 (id<MiscTreeBrowserNodes>)[[[self class] alloc] init];
}

- addChild:(id<MiscTreeBrowserNodes>)aNode at:(int)index
{	if(branches)
	{	if ([branches indexOf:aNode] == NX_NOT_IN_LIST)
		{	[branches insertObject:aNode at:index];
		}
	} else
	{	[self addBranch:aNode];
	} return self;
}

- addChild:(id<MiscTreeBrowserNodes>)aNode
{	return [self addChild:aNode at:[self childCount]];
}


- removeChildAt:(int)index
{	if (branches && (index >= 0) && (index < [self childCount]))
	{	id node = [branches objectAt:index];

		if ([node canFree])
		{	[branches removeObjectAt:index];
			[node free];
			return nil;			// success
		}
	} return self;				// failure, return non-zero value
}

- removeChild:(id<MiscTreeBrowserNodes>)aNode
{	if (branches)
	{	unsigned index = [branches indexOf:aNode];
		if (index != NX_NOT_IN_LIST)
			return [self removeChildAt:index];
	} return self;				// failure, return non-zero value
}

@end