#import "MorphView.h"
#import <appkit/appkit.h>

#define MORPH_DELAY 2000

@implementation MorphView

static void myWait(int millisecs)
/* Because the unix function usleep() is not thread-safe, I wrote a little 
 * function to delay the sorts for a specified number of milliseconds. 
 * Basically it allocates a port for itself and then tries to receive a 
 * message on that port.  I don't send any messages to that port, so it is 
 * waiting futilely.  However, I indicate the msg_receive should time out in 
 * the number of milliseconds I wanted to wait.
 */
{
msg_header_t nullMsg;
port_t aPort;
    
    if (port_allocate(task_self(), &aPort) != KERN_SUCCESS) return;
    nullMsg.msg_local_port = aPort;
    nullMsg.msg_size = sizeof(nullMsg);
    
    msg_receive(&nullMsg,RCV_TIMEOUT,millisecs);// wait until timeout
    port_deallocate(task_self(),aPort);		// clean up
}

- initFrame: (const NXRect *) theFrame
{
	return [self initFrame: theFrame images: 0 delay: 1 delta: 0.05];
}

- initFrame:(const NXRect *) theFrame images: images delay:(int) delay
	delta:(float) delta
{
	[super initFrame: theFrame];
	[self setImages: images delay: delay delta: delta];

	return self;
}

- setImages: images delay:(int) delay delta:(float) delta
{
	if( imageList != 0 )
		[imageList free];
	if( images != nil )
		imageList = [images copy];
	else
		imageList = [[List alloc] initCount: 0];
	imageDelta = delta;
	imageDelay = delay;
	imageIndex = -1;

	return self;
}

- setDelegate: newDelegate
{
id oldDelegate = delegate;

	delegate = newDelegate;
	return oldDelegate;
}

- morph: sender
{
float delta;
int count;
id image0, image1;

	if( [sender isKindOf: [Button class]] == YES )
		morphTrigger = [sender setEnabled: NO];
	count = [imageList count];
	imageIndex ++;
	image0 = [imageList objectAt: imageIndex];
	image1 = [imageList objectAt: imageIndex + 1];
	[self lockFocus];
	if( [delegate hasDrawMethodFor: image0 imageNum: imageIndex] == YES )
		[delegate performDrawFor: image0 imageNum: imageIndex inView: self];
	// Perform the dissolution
	for(delta = 0; delta <= 1.0; delta += imageDelta)
	{
		[image0 composite:NX_SOVER toPoint: &bounds.origin];
		[image1 dissolve: delta toPoint: &bounds.origin];
		[window flushWindow];
		myWait(imageDelay);
	}
	[image1 composite: NX_SOVER toPoint: &bounds.origin];
	[window flushWindow];
	[self unlockFocus];

	if( imageIndex  < count - 1 )
	{
		[self perform: _cmd with: self 
			afterDelay: MORPH_DELAY cancelPrevious: YES];
	}
	else
	{
		imageIndex = -1;
		[morphTrigger setEnabled: YES];
		[self display];
	}

	return self;
}

- drawSelf:(const NXRect *) rects :(int) rectCount
{
	[[imageList objectAt: 0] composite: NX_SOVER toPoint: &bounds.origin];
	return self;
}

- (int) count
{
	return [imageList count];
}
- (float) delta
{
	return imageDelta;
}

@end
/* RCS Information:
	$Author: me $;
	$Date: 93/02/23 02:00:54 $;
	$Source: /usr1/me/NeXTSrc/MyClasses/RCS/MorphView.m,v $;
	Revision: 1.3 $;
*/
