
/*
	Copyright 1993  Jeremy Slade.  All rights reserved.
*/

#import "DynamicItems.h"

#import "DynamicItemSpec.h"
#import "Globals.h"
#import "ItemCell.h"


// DynamicItem update handler
void	updateHandler ( DPSTimedEntry teNum, double now, Group *self );


@implementation Group ( DynamicItems )


// -------------------------------------------------------------------------
//   DynamicItemSpecs
// -------------------------------------------------------------------------


- dynamicItemSpecs
/*
	Returns a List containing all the dynamic items (instances of DynamicItemSpec) for this group.
*/
{
	return ( dynamicItemSpecs );
}



- dynamicItemSpecMatching:(const char *)itemSpec
/*
	Search the dynamicItem list for an object matching itemSpec and return it
*/
{
	int i, count;
	id	spec;
	
	count = [dynamicItemSpecs count];
	for ( i=0; i<count; i++ ) {
		if ( !strcmp ( [(spec = [dynamicItemSpecs objectAt:i]) expression],
			itemSpec ) )
				return ( spec );
	}
	
	return ( nil ); // No match found
}



- addDynamicItemSpec:(const char *)itemSpec
/*
	Add itemSpec to the dynamicItemSpecs list
*/
{
	if ( ![self dynamicItemSpecMatching:itemSpec] ) {
		[dynamicItemSpecs addObject:
			[[DynamicItemSpec alloc] initExpr:itemSpec]];
		[self setChanged:YES];
	}
	
	return ( self );
}



- removeDynamicItemSpec:(const char *)itemSpec
/*
	Remove itemSpec from the dynamicItemSpecs list
*/
{
	id spec;
	
	if ( spec = [self dynamicItemSpecMatching:itemSpec] ) {
		[dynamicItemSpecs removeObject:spec];
		[self setChanged:YES];
	}
	
	return ( self );
}



- enableDynamicItemSpec:(const char *)itemSpec
/*
	Enable the dynamicItemSpec matching itemSpec
*/
{
	id spec;

	if ( spec = [self dynamicItemSpecMatching:itemSpec] ) {
		[spec setEnabled:YES];
		[self setChanged:YES];
	}
	
	return ( self );
}



- disableDynamicItemSpec:(const char *)itemSpec
/*
	Disable the dynamicItemSpec matching itemSpec
*/
{
	id spec;

	if ( spec = [self dynamicItemSpecMatching:itemSpec] ) {
		[spec setEnabled:NO];
		[self setChanged:YES];
	}

	return ( self );
}



// -------------------------------------------------------------------------
//   Updating DynamicItems
// -------------------------------------------------------------------------


- setUpdateInterval:(float)interval
{
	[self stopDynamicUpdate];
	if ( dynamicUpdateInterval != interval ) {
		dynamicUpdateInterval = interval;
		[self setChanged:YES];
	}
	[self startDynamicUpdate];
	
	return ( self );
}



- (float)updateInterval
{
	return ( dynamicUpdateInterval );
}



- startDynamicUpdate
{
	[self stopDynamicUpdate];

	// Do this automatically when the updating starts
	[self perform:@selector(updateDynamicItems:) with:self 		afterDelay:0 cancelPrevious:YES];
	
	if ( dynamicUpdateInterval == 0.0 )
		return ( self );
	 updateTE = DPSAddTimedEntry ( dynamicUpdateInterval,
		(DPSTimedEntryProc)updateHandler, (void *)self, NX_BASETHRESHOLD+1 );

	return ( self );
}



- stopDynamicUpdate
{
	if ( updateTE ) {
		DPSRemoveTimedEntry ( updateTE );
		updateTE = 0;
	}
	
	return ( self );
}
	


- updateDynamicItems:sender
/*
	Called by the update timed-entry, or manually thorugh a menu item.  Tell all of the DynamicItemSpecs to update...
*/
{
//if ( DEBUGGING ) printf ( "Performing DynamicUpdate...\n" );
	[self removeDynamicItems];
	[dynamicItemSpecs
		makeObjectsPerform:@selector(addMatchingItemsToGroup:)
		with:self];
	if ( [self doesSortItems] ) {
		BOOL wasChanged = [self isChanged];
		[self sortItems];
		[self setChanged:wasChanged];
	}
//if ( DEBUGGING ) printf ( "	Done.\n" );
	return ( self );
}



// -------------------------------------------------------------------------
//   Working with DynamicItems
// -------------------------------------------------------------------------


- addDynamicItem:item
/*
	Add the DynamicItem to the group, but don't mark as changed.
*/
{
	if ( ![self itemExists:[item path]] && [self isAllowedType:[item path]] ) {
		[self addObject:item];
		[folder setNeedsLoadBrowser:YES];
		return ( self );
	} else
		return ( nil );
}



- removeDynamicItems
/*
	Search throug the group and remove all DynamicItems
*/
{
	register int i;
	register id item;
	
	i = numElements;
	while ( i-- ) if ( [(item = [self objectAt:i]) isDynamic] ) [self removeObjectAt:i];
	return ( self );
}




- (int)countDynamicItems
/*
	Search through the group and count all DynamicItems
*/
{
	register int i, count;
	
	i = numElements;
	count = 0;
	while ( i-- ) if ( [[self objectAt:i] isDynamic] ) count++;
	return ( count );
}




@end



// DynamicItem update handler
void	updateHandler ( DPSTimedEntry teNum,
	double now, Group *self )
{
	[self updateDynamicItems:self];
	return;
}
	
