//
//	MiscColor.m -- a wrapper class around the NXColor functions
//		Written by Don Yacktman (c) 1994 by Don Yacktman.
//				Version 1.0.  All rights reserved.
//
//		This notice may not be removed from this source code.
//
//	This object is included in the MiscKit by permission from the author
//	and its use is governed by the MiscKit license, found in the file
//	"LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
//	for a list of all applicable permissions and restrictions.
//	

#import <misckit/misckit.h>

@implementation MiscColor

+ (BOOL)canInitFromPasteboard:(Pasteboard *)pasteboard
{ // ***** need to also check for the color object type
	const char *pBoardTypes[2] = { NXColorPboardType, NULL };
	if ([pasteboard findAvailableTypeFrom:pBoardTypes num:1]
			== NXColorPboardType) return YES;
	return NO;
}

+ newFromPasteBoard:(Pasteboard *)pasteboard
{
	return [[self alloc] initFromPasteBoard:pasteboard];
}

+ newColor:(NXColor)color
{
	return [[self alloc] initColor:color];
}

- init
{
	return [self initColor:NX_COLORWHITE];
}

- initColor:(NXColor)color
{
	[self setColor:color];
	[self setDelegate:nil];
	return self;
}

- initFromPasteBoard:(Pasteboard *)pasteboard
{
	if (![[self class] canInitFromPasteboard:pasteboard]) {
		[self free];
		return nil;
	}
	return [[self init] setFromPasteBoard:pasteboard];
}

- initColorFromPixel:(NXPoint *)location
{
	return [self initColor:NXReadPixel(location)];
}

- readFromPasteBoard:(Pasteboard *)pasteboard
{ // ***** need to also deal with color object type
	[self setColor:NXReadColorFromPasteboard(pasteboard)];
	return self;
}

- setFromPasteBoard:(Pasteboard *)pasteboard
{
	return [self readFromPasteBoard:pasteboard];
}

- writeToPasteBoard:(Pasteboard *)pasteboard
{	// Need to add a pasteboard type for the color OBJECT, too... *****
	NXWriteColorToPasteboard(pasteboard, [self actualColor]);
	return self;
}

- setRedComponent:(float)red
{
	[self setColor:NXChangeRedComponent([self actualColor], red)];
	return self;
}

- setGreenComponent:(float)green
{
	[self setColor:NXChangeGreenComponent([self actualColor], green)];
	return self;
}

- setBlueComponent:(float)blue
{
	[self setColor:NXChangeBlueComponent([self actualColor], blue)];
	return self;
}

- setCyanComponent:(float)cyan
{
	[self setColor:NXChangeCyanComponent([self actualColor], cyan)];
	return self;
}

- setMagentaComponent:(float)magenta
{
	[self setColor:NXChangeMagentaComponent([self actualColor], magenta)];
	return self;
}

- setYellowComponent:(float)yellow
{
	[self setColor:NXChangeYellowComponent([self actualColor], yellow)];
	return self;
}

- setBlackComponent:(float)black
{
	[self setColor:NXChangeBlackComponent([self actualColor], black)];
	return self;
}

- setHueComponent:(float)hue
{
	[self setColor:NXChangeHueComponent([self actualColor], hue)];
	return self;
}

- setSaturationComponent:(float)saturation
{
	[self setColor:
			NXChangeSaturationComponent([self actualColor], saturation)];
	return self;
}

- setBrightnessComponent:(float)brightness
{
	[self setColor:
			NXChangeBrightnessComponent([self actualColor], brightness)];
	return self;
}

- setGrayComponent:(float)gray
{
	[self setColor:NXChangeGrayComponent([self actualColor], gray)];
	return self;
}

- setAlphaComponent:(float)alpha
{
	[self setColor:NXChangeAlphaComponent([self actualColor], alpha)];
	return self;
}

- setColor:(NXColor)color
{
	theColor = color;
	return self;
}

- setColorFromObject:object
{
	if ([object respondsTo:@selector(actualColor)]) {
		[self setColor:[object actualColor]];
		return self;
	} else if ([object respondsTo:@selector(color)]) {
		[self setColor:[object color]];
		return self;
	}
	return nil;
}

- setColorFromPixel:(NXPoint *)location
{
	[self setColor:NXReadPixel(location)];
	return self;
}

- (NXColor)color { return [self filterColor:[self actualColor]]; }
- (NXColor)actualColor { return theColor; }

- display
{
	[self setColor]; // throw away return value
	return self;
}

- (NXColor)filterColor:(NXColor)input
{
	return input;
}

- (BOOL)setColor
{
	BOOL printOK = YES;
	id theDelegate = [self delegate];
	NXColor realColor = [self actualColor];
	if ([theDelegate respondsTo:@selector(willSendColorToPS:shouldPrint:)])
		realColor = [theDelegate willSendColorToPS:[self actualColor]
				shouldPrint:&printOK];
	if (printOK) {
		NXColor filtered = [self filterColor:realColor];
		NXSetColor(filtered);
		if ([theDelegate respondsTo:@selector(didSendColorToPS:)])
			[theDelegate didSendColorToPS:filtered];
	}
	return printOK;
}

- getGray:(float *)gray
{
	NXConvertColorToGray([self actualColor], gray);
	return self;
}

- getGray:(float *)gray alpha:(float *)alpha
{
	NXConvertColorToGrayAlpha([self actualColor], gray, alpha);
	return self;
}

- getRed:(float *)red green:(float *)green blue:(float *)blue
{
	NXConvertColorToRGB([self actualColor], red, green, blue);
	return self;
}

- getRed:(float *)red green:(float *)green blue:(float *)blue
		alpha:(float *)alpha
{
	NXConvertColorToRGBA([self actualColor], red, green, blue, alpha);
	return self;
}

- getHue:(float *)hue saturation:(float *)saturation
		brightness:(float *)brightness
{
	NXConvertColorToHSB([self actualColor], hue, saturation, brightness);
	return self;
}

- getHue:(float *)hue saturation:(float *)saturation
		brightness:(float *)brightness alpha:(float *)alpha
{
	NXConvertColorToHSBA([self actualColor],
			hue, saturation, brightness, alpha);
	return self;
}

- getCyan:(float *)cyan magenta:(float *)magenta yellow:(float *)yellow
		black:(float *)black
{
	NXConvertColorToCMYK([self actualColor], cyan, magenta, yellow, black);
	return self;
}

- getCyan:(float *)cyan magenta:(float *)magenta yellow:(float *)yellow
		black:(float *)black alpha:(float *)alpha
{
	NXConvertColorToCMYKA([self actualColor],
			cyan, magenta, yellow, black, alpha);
	return self;
}

- setGray:(float)gray
{
	[self setColor:NXConvertGrayToColor(gray)];
	return self;
}

- setGray:(float)gray alpha:(float)alpha
{
	[self setColor:NXConvertGrayAlphaToColor(gray, alpha)];
	return self;
}

- setRed:(float)red green:(float)green blue:(float)blue
{
	[self setColor:NXConvertRGBToColor(red, green, blue)];
	return self;
}

- setRed:(float)red green:(float)green blue:(float)blue alpha:(float)alpha
{
	[self setColor:NXConvertRGBAToColor(red, green, blue, alpha)];
	return self;
}

- setHue:(float)hue saturation:(float)saturation
		brightness:(float)brightness
{
	[self setColor:NXConvertHSBToColor(hue, saturation, brightness)];
	return self;
}

- setHue:(float)hue saturation:(float)saturation
		brightness:(float)brightness alpha:(float)alpha
{
	[self setColor:NXConvertHSBAToColor(hue, saturation, brightness, alpha)];
	return self;
}

- setCyan:(float)cyan magenta:(float)magenta yellow:(float)yellow
		black:(float)black
{
	[self setColor:NXConvertCMYKToColor(cyan, magenta, yellow, black)];
	return self;
}

- setCyan:(float)cyan magenta:(float)magenta yellow:(float)yellow
		black:(float)black alpha:(float)alpha
{
	[self setColor:NXConvertCMYKAToColor(cyan, magenta, yellow, black, alpha)];
	return self;
}

- (BOOL)isEqualColor:anObject
{
	if ([anObject respondsTo:@selector(actualColor)]) {
		return NXEqualColor([self actualColor], [anObject actualColor]);
	} else if ([anObject respondsTo:@selector(color)]) {
		return NXEqualColor([self color], [anObject color]);
	}
	return NO;
}

- (BOOL)isEqualToColor:(NXColor)color
{
	return NXEqualColor([self color], color);
}

- (BOOL)isEqual:anObject
{
	if ([anObject class] != [self class]) return NO;
	return [self isEqualColor:anObject];
}

- read:(NXTypedStream *)stream
{
	[super read:stream];
	[self setColor:NXReadColor(stream)];
	[self setDelegate:NXReadObject(stream)];
	return self;
}

- write:(NXTypedStream *)stream
{
	[super write:stream];
	NXWriteColor(stream, [self actualColor]);
	NXWriteObject(stream, [self delegate]);
	return self;
}

// NXTransport protocol:  (I hope these will work, since I don't know another
//		way to encode and pass a color through a portal!)
- encodeUsing:(id <NXEncoding>)portal
{
	NXColor sendColor = [self actualColor];
	id sendDelegate = [self delegate];
	[portal encodeData:&sendColor ofType:@encode(NXColor)];
	[portal encodeData:&sendDelegate ofType:"@"];
	return self;
}

- decodeUsing:(id <NXDecoding>)portal
{
	NXColor newColor;
	id newDelegate;
	[portal decodeData:&newColor ofType:@encode(NXColor)];
	[portal decodeData:&newDelegate ofType:"@"];
	[self setColor:newColor];
	[self setDelegate:newDelegate];
	return self;
}

- encodeRemotelyFor:(NXConnection *)connection
	freeAfterEncoding:(BOOL *)flagp isBycopy:(BOOL)isByCopy
{
	if (isByCopy) {
		*flagp = NO; // object will not be freed (ie, copy,  not move)
		return self; //encode object (copy it)
	}
	*flagp = NO;
	// super will encode the proxy otherwise
	return [super encodeRemotelyFor:connection
				freeAfterEncoding:flagp isBycopy:isByCopy];
}

// Interface Builder support
- (const char *)getInspectorClassName { return "MiscColorInspector"; }
- (NXImage *)getIBImage { return [NXImage findImageNamed:"MiscColorObj"]; }

- (float)redComponent { return NXRedComponent([self actualColor]); }
- (float)greenComponent { return NXGreenComponent([self actualColor]); }
- (float)blueComponent { return NXBlueComponent([self actualColor]); }
- (float)cyanComponent { return NXCyanComponent([self actualColor]); }
- (float)magentaComponent { return NXMagentaComponent([self actualColor]); }
- (float)yellowComponent { return NXYellowComponent([self actualColor]); }
- (float)blackComponent { return NXBlackComponent([self actualColor]); }
- (float)hueComponent { return NXHueComponent([self actualColor]); }
- (float)saturationComponent { return NXSaturationComponent([self actualColor]); }
- (float)brightnessComponent { return NXBrightnessComponent([self actualColor]); }
- (float)grayComponent { return NXGrayComponent([self actualColor]); }
- (float)alphaComponent { return NXAlphaComponent([self actualColor]); }

+ findColorNamed:(const char *)aName inList:(const char *)aListName
{
	NXColor newColor;
	if (!NXFindColorNamed(aListName, aName, &newColor)) return nil;
	return [[self alloc] initColor:newColor];
}

- (const char *)colorName { return NXColorName([self actualColor]); }
- (const char *)colorListName { return NXColorListName([self actualColor]); }

- delegate { return delegate; }
- setDelegate:anObject
{
	id ret = delegate;
	delegate = anObject;
	return ret;
}

@end


// Examples of a NULL delegate
@implementation MiscColor(delegate)

- (NXColor)willSendColorToPS:(NXColor)color shouldPrint:(BOOL *)printOK
{
	*printOK = YES;
	return color;
}

- didSendColorToPS:(NXColor)color
{
	return self;
}

@end
