#import "UITabActionCell.h"

#import <appkit/appkit.h>

#import <objc/List.h>

#define TAB_IMAGE_WIDTH		14.0
#define TAB_IMAGE_HEIGHT	17.0
#define HALF_TAB_WIDTH		TAB_IMAGE_WIDTH / 2

@implementation UITabActionCell


// Methods Overridden From the Superclass
- initTextCell:(const char *)aString
// Initializes a new instance of the receiver.
{
    [super initTextCell:aString];

 // finish the initialization process 
    [self finishInitializing];

    return self;
}

- awake
// Performs additional intialization of the receiver after reading
// from an NXTypedStream.
{
 // do the superclass' awake method 
    [super awake];

 // finish the initializing process 
    [self finishInitializing];

    return self;
}

- setFont:fontObj
// Sets the receiver's font to <fontObj> and fetches font info used
// during the receiver's display.
{
 // Do the superclass' init method 
    [super setFont:fontObj];

 // Grab the font information for the contents of the cell 
    NXTextFontInfo(fontObj, &ascender, &descender, &lineHeight);

    return self;
}

- drawInside:(const NXRect *)cellFrame inView:controlView
// Draws the receiver inside <cellFrame> in view <controlView>.
{
    NXPoint	leftImageOrigin,
    		rightImageOrigin;
		
    NXRect 	textFrame,
    		lowerBezelFrame;
		
    List	*controlCellList;
    int		index;

 // if there are no contents, then punt... 
    if (!contents) {
	return self;
    }

 // if <controlView> is not a kind of Matrix (i.e. in IB)
    if (![controlView isKindOf:[Matrix class]]) {
		[super drawInside:cellFrame inView:controlView];	
    	return self;
    }

 // set drawing to opaque
    PSsetalpha(1.0);

	PSsetgray(NX_DKGRAY);
	NXRectFill(cellFrame);

 // fetch information about ourselves in our Matrix
    controlCellList = [controlView cellList];
    index = [controlCellList indexOf:self];
        

 // set up the lowerBezelFrame that will be used for drawing the bezel
 // at our bottom
    NXSetRect(&lowerBezelFrame,

	      NX_X(cellFrame) + HALF_TAB_WIDTH,
	      NX_MAXY(cellFrame) - 1.0,

	      NX_WIDTH(cellFrame),
	      1.0);

 // set textFrame to cellFrame 
    textFrame = *cellFrame;

 // set up the leftImageOrigin 
    leftImageOrigin.x = NX_X(cellFrame);
    leftImageOrigin.y = NX_MAXY(cellFrame);

 // if index is 0 (we are the first cell) 
    if (index == 0) {
    // if we are selected 
	if ([self isSelected]) {
	// composite tabBeginSelectedImage to leftImageOrigin 
	    [tabBeginSelectedImage
	    	composite:NX_SOVER
		toPoint:&leftImageOrigin];
	} else {
	// otherwise, composite tabBeginImage to leftImageOrigin 
	    [tabBeginImage
	    	composite:NX_SOVER
		toPoint:&leftImageOrigin];

	// subtract a HALF_TAB_WIDTH from lowerBezelFrame's x 
	    lowerBezelFrame.origin.x -= HALF_TAB_WIDTH;
	}

    // add a TAB_IMAGE_WIDTH to textFrame's x 
	textFrame.origin.x += TAB_IMAGE_WIDTH;

     // subtract a TAB_IMAGE_WIDTH plus HALF_TAB_WIDTH minus 1.0
     // from textFrame's width
	textFrame.size.width -= TAB_IMAGE_WIDTH + HALF_TAB_WIDTH - 1.0;
    } else {
    // subtract a HALF_TAB_WIDTH from leftImageOrigin's x 
	leftImageOrigin.x -= HALF_TAB_WIDTH;

    // if the cell to left of us is selected 
	if ([[controlCellList objectAt:index - 1] isSelected]) {
	// composite tabBeginImage to leftImageOrigin 
	    [tabBeginImage
	    	composite:NX_SOVER
		toPoint:&leftImageOrigin];

	// composite tabEndSelectedImage to leftImageOrigin 
	    [tabEndSelectedImage
	    	composite:NX_SOVER
		toPoint:&leftImageOrigin];
	} else if ([self isSelected]) {
	// otherwise, if we are selected 

	// composite tabEndImage to leftImageOrigin 
	    [tabEndImage
	    	composite:NX_SOVER
	    	toPoint:&leftImageOrigin];

	// composite tabBeginSelectedImage to leftImageOrigin 
	    [tabBeginSelectedImage
	    	composite:NX_SOVER
	     toPoint:&leftImageOrigin];
	} else {
	// composite tabBeginImage to leftImageOrigin 
	    [tabBeginImage
	    	composite:NX_SOVER
		toPoint:&leftImageOrigin];

	// composite tabEndImage to leftImageOrigin 
	    [tabEndImage
	    	composite:NX_SOVER
		toPoint:&leftImageOrigin];

	// subtract a HALF_TAB_WIDTH from lowerBezelFrame's x 
	    lowerBezelFrame.origin.x -= TAB_IMAGE_WIDTH;

	// add 1.0 to lowerBezelFrame's width 
	    lowerBezelFrame.size.width += 1.0;
	}

    // add a HALF_TAB_WIDTH to textFrame's x 
	textFrame.origin.x += HALF_TAB_WIDTH;

    // subtract a TAB_IMAGE_WIDTH minus 1.0 from textFrame's width 
	textFrame.size.width -= TAB_IMAGE_WIDTH - 1.0;
    }

 // if index is less than controlCellList's count minus 1 then we're
 // not the last cell, and...
    if (index < [controlCellList count] - 1) {
    // draw the cell to the right of us 
	[controlView drawCell:[controlCellList objectAt:index + 1]];
    } else {
    // set up the rightImageOrigin 
	rightImageOrigin.x = NX_X(cellFrame) + NX_WIDTH(cellFrame)
	  - TAB_IMAGE_WIDTH;
	rightImageOrigin.y = NX_Y(cellFrame) + NX_HEIGHT(cellFrame);

    // if we are selected 
	if ([self isSelected]) {
	// composite tabEndSelectedImage to rightImageOrigin 
	    [tabEndSelectedImage
	    	composite:NX_SOVER
	     	toPoint:&rightImageOrigin];
	} else {
	// composite tabEndImage to rightImageOrigin 
	    [tabEndImage
	    	composite:NX_SOVER
		toPoint:&rightImageOrigin];
	}

    // subtract a TAB_IMAGE_WIDTH from textFrame's width 
	textFrame.size.width -= HALF_TAB_WIDTH;

    // add a HALF_TAB_WIDTH to lowerBezelFrame's width 
	lowerBezelFrame.size.width += HALF_TAB_WIDTH;
    }

 // erase the cell 

 // if we are selected 
    if ([self isSelected]) {
    // set our drawing color to NX_LTGRAY 
	PSsetgray(NX_LTGRAY);
    } else {
	PSsetgray(.5);
    }
	
	textFrame.size.height = TAB_IMAGE_HEIGHT;
	textFrame.origin.y = NX_MAXY(cellFrame)-TAB_IMAGE_HEIGHT;

 // fill in textFrame 
    NXRectFill(&textFrame);

 // now draw the upper bezel 

 // set our drawing color to NX_LTGRAY 
 // if we are selected 
    if ([self isSelected]) {
    // set our drawing color to NX_LTGRAY 
	PSsetgray(NX_WHITE);
    } else {
	PSsetgray(NX_LTGRAY);
    }

 // set textFrame's height to 1.0 
    textFrame.size.height = 1.0;

 // fill in textFrame 
    NXRectFill(&textFrame);

 // now draw the text 

 // set our drawing color to NX_BLACK 
    PSsetgray(NX_BLACK);

 // draw the cell's contents 

	if (NXDrawingStatus == NX_DRAWING && [[self font] screenFont])
	  [[[self font] screenFont] set];
	else
	  [[self font] set];

    PSmoveto(NX_X(&textFrame),
    NX_Y(&textFrame) + lineHeight - descender + 1.0);
    PSshow(contents);

 // if we are not selected 
    if (![self isSelected]) {
    // draw the lower bezel 

    // set our drawing color to NX_WHITE 
	PSsetgray(NX_WHITE);

    // fill in lowerBezelFrame 
	NXRectFill(&lowerBezelFrame);
    }
    return self;
}

- highlight:(const NXRect *)cellFrame inView:aView lit:(BOOL)flag
{
	[super highlight:cellFrame inView:aView lit:flag];
	[self drawInside:cellFrame inView:aView];
	return self;
}

- calcCellSize:(NXSize *)theSize inRect:(const NXRect *)aRect
{
	theSize->height = TAB_IMAGE_HEIGHT;
	theSize->width =  (2*TAB_IMAGE_WIDTH+
					[[self font] getWidthOf:[self stringValue]]);
	return self;
}

- (BOOL)trackMouse:(NXEvent *)theEvent
			inRect:(const NXRect *)cellFrame
			ofView:controlView
{
	BOOL	boolValue = [super trackMouse:(NXEvent *)theEvent
									inRect:(const NXRect *)cellFrame
									ofView:controlView];

	if (theEvent->type == NX_MOUSEUP)
	{
		[self incrementState];
	}
	
	return boolValue;
}

- (BOOL)startTrackingAt:(const NXPoint *)startPoint inView:aView
{
	[aView sendAction];
	return NO;
}

// Other Instance Methods 
- finishInitializing
{
 // get the "tabBegin" image 
    if (!tabBeginImage) {
	tabBeginImage = [NXImage findImageNamed:"TabBegin"];
    }
 // get the "tabEnd" image 
    if (!tabEndImage) {
	tabEndImage = [NXImage findImageNamed:"TabEnd"];
    }
 // get the "tabBeginSelected" image 
    if (!tabBeginSelectedImage) {
	tabBeginSelectedImage = [NXImage findImageNamed:"TabBeginSelected"];
    }
 // Get the "tabEndSelected" image 
    if (!tabEndSelectedImage) {
	tabEndSelectedImage = [NXImage findImageNamed:"TabEndSelected"];
    }
 
 // all text displayed will be in Helvetica, 12 point 
    //[self setFont:[Font newFont:"Helvetica" size:12.0]];
    [self setFont:[self font]];

 // send the action on no event; we'll handle sending the event ourselves
 	[self sendActionOn:NX_NULLEVENTMASK];

    return self;
}

// Accessor Methods

- (BOOL)isSelected
{
	return (cFlags1.highlighted || cFlags1.state);
}
@end