/* Misc3DMetaDriver.m				 
 *
 * The MetaDriver is a driver wrapper. It will transparently switch between
 * drivers taking care that there will be no conflicts. It is not a real driver
 * and so all standard events will be passed to the realDriver. (Confuising ?!)
 *
 * For more interface-info see the header file. More in depth information
 * can be found in the source-code.
 *
 * Written by: 		Thomas Engel
 * Created:    		10.04.1994 (Copyleft)
 * Last modified: 	18.04.1994
 */

#import "Misc3DMetaDriver.h"

@implementation Misc3DMetaDriver

- setTarget:anObject
{
	target = anObject;
	if( !realDriver ) return self;
	return [realDriver setTarget:anObject];
}

- target
{
	if( !realDriver ) return target;
	return [realDriver target];
}

- (oneway void)enableEvents
{
	sendEvents = YES;
	[realDriver enableEvents];
	return;
}

- (oneway void)disableEvents
{
	sendEvents = NO;
	[realDriver disableEvents];
	return;
}

- (oneway void)syncEvents
{
	[realDriver syncEvents];
	return;
}

- setUseExternalSync:(BOOL)aFlag
{
	syncEvents = aFlag;
	return [realDriver setUseExternalSync:aFlag];
}

- (BOOL)doesUseExternalSync
{
	if( !realDriver ) return syncEvents;
	return [realDriver doesUseExternalSync];
}

- (BOOL)areEventsEnabled
{
	if( !realDriver ) return sendEvents;
	return [realDriver areEventsEnabled];
}

- setRealDriver:aDriver
{
	// Let's check the new driver. If it does conform to our driver protocol
	// we will accept it.
	// We will use the old target but only the new driver will know about
	// it. Ensuring that only one device is active at the same time.
	// 
	// We have to transfer all the settings to the other driver. But only
	// the general event settings will be transferred!
	
	id		oldDriver;
	id		theTarget;
	BOOL	doesSend;
	BOOL	doesSync;
	
	if( [aDriver conformsTo:@protocol(Misc3DDeviceDriverProtocol)] )
	{
		// If our old target refuses to drop its target we won't install
		// the new driver. 
		// If there was no old driver we will serve as the source for all the
		// settings. This class keeps track of all the settings passed to a
		// realDriver so this should work real nice.
		
		if( realDriver )
				oldDriver = realDriver;
		else	oldDriver = self;
		
		// Our code tries to ensure that the old driver will be deactivated
		// before the new one becomes active.
		
		theTarget = [oldDriver target];
		doesSend = [oldDriver areEventsEnabled];
		doesSync = [oldDriver doesUseExternalSync];
		
		if( [oldDriver setTarget:nil] )
		{
			[oldDriver disableEvents];
			
			[aDriver setTarget:theTarget];
			if( doesSend )
					[aDriver enableEvents];
			else	[aDriver disableEvents];
			[aDriver setUseExternalSync:doesSync];
			
			realDriver = aDriver;
		}
	}
	
	return self;
}

- realDriver
{
	return realDriver;
}

@end

/*
 * History: 18.04.94 Added the setTarget:nil feature.
 *
 *			10.04.94 Invented to allow device switching while device is in
 *					 use. 
 *
 *
 * Bugs: - Not really. see the .h file.
 */