//=============================================================================
//
//		Copyright (C) 1995-1996 by Paul S. McCarthy and Eric Sunshine.
//				Written by Paul S. McCarthy and Eric Sunshine.
//							All Rights Reserved.
//
//		This notice may not be removed from this source code.
//
//		This object is included in the MiscKit by permission from the authors
//		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.
//		
//=============================================================================
//-----------------------------------------------------------------------------
// MiscBorderCell.M
//
//		Cell class used by MiscBorderView to manage column headings and row 
//		labels for MiscTableScroll.	 
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// $Id: MiscBorderCell.M,v 1.5 96/09/13 12:32:36 zarnuk Exp $
// $Log:		MiscBorderCell.M,v $
//	Revision 1.5  96/09/13	12:32:36  zarnuk
//	Added the image instance variable, and support for drawing it.
//	
//	Revision 1.4  96/08/30	14:49:20  sunshine
//	No longer directly accesses cFlags.
//-----------------------------------------------------------------------------
#import "MiscBorderCell.h"

extern "Objective-C" {
#import <appkit/Font.h>
#import <appkit/NXImage.h>
#import <appkit/Text.h>
#import <dpsclient/wraps.h>
}

extern "C" {
#import <math.h>
}

#define BORDER_TOP		2		// 2 pixels for top	   border
#define BORDER_BOTTOM	1		// 1 pixel	for bottom border
#define BORDER_LEFT		2		// 2 pixels for left   border
#define BORDER_RIGHT	1		// 1 pixel	for right  border

#define BORDER_WIDTH	(BORDER_LEFT + BORDER_RIGHT)
#define BORDER_HEIGHT	(BORDER_TOP + BORDER_BOTTOM)

#define RESIZE_WIDTH	3		// Resize zone is 4 pixels on right.

@implementation MiscBorderCell

//-----------------------------------------------------------------------------
// -setImage:
//-----------------------------------------------------------------------------
- setImage:img
	{
	image = img;
	return self;
	}


//-----------------------------------------------------------------------------
// -initTextCell:
//-----------------------------------------------------------------------------
- initTextCell: (char const*) s
	{
	[super initTextCell:s];
	[self setBordered:NO];
	[self setWrap:NO];
	[self setAlignment: NX_CENTERED];
	[self setFont: [Font boldSystemFontOfSize:12.0 matrix:NX_FLIPPEDMATRIX]];
	return self;
	}


//-----------------------------------------------------------------------------
// -backgroundGray
//-----------------------------------------------------------------------------
- (float) backgroundGray
	{
	return [self state] ? (1.0/6.0) : NX_DKGRAY;
	}


//-----------------------------------------------------------------------------
// -setTextAttributes:
//-----------------------------------------------------------------------------
- setTextAttributes:textObject
	{
	[super setTextAttributes:textObject];
	[textObject setTextGray:NX_WHITE];
	[textObject setBackgroundGray: [self backgroundGray]];
	return textObject;
	}


//-----------------------------------------------------------------------------
// -calcCellSize:inRect:
//-----------------------------------------------------------------------------
- calcCellSize:(NXSize*)theSize inRect:(NXRect const*)aRect
	{
	[super calcCellSize:theSize inRect:aRect];
	theSize->width += BORDER_WIDTH + RESIZE_WIDTH;
	theSize->height += BORDER_HEIGHT;
	if (image != 0)
		{
		NXSize sz;
		[image getSize:&sz];
		theSize->width += sz.width;
		}
	return self;
	}


//-----------------------------------------------------------------------------
// -drawInside:inView:
//-----------------------------------------------------------------------------
- drawInside:(NXRect const*)p inView:v
	{
	// Assume the view is flipped.
	NXRect r;
	PSsetgray( [self backgroundGray] );
	NXSetRect( &r, NX_X(p) + BORDER_LEFT, NX_Y(p) + BORDER_TOP,
				   NX_WIDTH(p) - BORDER_WIDTH, NX_HEIGHT(p) - BORDER_HEIGHT );
	NXRectFill( &r );

	if (image != 0)
		{
		NXSize sz;
		[image getSize:&sz];

		NXPoint pt;
		pt.x = NX_MAXX(p) - BORDER_RIGHT - RESIZE_WIDTH;
		pt.y = NX_MAXY(p) - BORDER_BOTTOM;

		NXCoord max_height = floor( NX_HEIGHT(p) - BORDER_HEIGHT );
		NXCoord max_width = floor( NX_WIDTH(p) - BORDER_WIDTH - RESIZE_WIDTH );

		BOOL const too_high = sz.height > max_height;
		BOOL const too_wide = sz.width > max_width;
		if (too_high || too_wide)
			{
			NXRect q = { {0,0}, {sz.width, sz.height} };
			if (too_high)
				{
				q.size.height = max_height;
				q.origin.y = floor( (sz.height - max_height) / 2 );
				}
			else
				{
				// Center image vertically.
				pt.y = floor( pt.y - ((max_height - sz.height) / 2) );
				}
			if (too_wide)
				{
				q.size.width = max_width;
				q.origin.x = floor( (sz.width - max_width) / 2 );
				}
			sz = q.size;
			pt.x -= sz.width;
			[image composite:NX_SOVER fromRect:&q toPoint:&pt];
			}
		else
			{
			// Center image vertically.
			pt.y = floor( pt.y - ((max_height - sz.height) / 2) );
			pt.x -= sz.width;
			[image composite:NX_SOVER toPoint:&pt];
			}

		r.size.width -= (sz.width + RESIZE_WIDTH);
		}

	[super drawInside:&r inView:v];
	return self;
	}


//-----------------------------------------------------------------------------
// -drawSelf:inView:
//
//		Draw light gray lines at top and left edges.  Draw white lines just
//		inside light gray lines at top and left edges.	Draw black lines at
//		bottom and right edges.	 Draw dark gray pixel at junction of white
//		and black lines (in lower-left and upper-right corners).
//
//		The lines are derived from a table of scalers and constants which are
//		applied to the cellFrame(cf) using the following formulas:
//				x = cf.x * xScaler + cf.maxx * maxxScaler + xConst
//				y = cf.y * yScaler + cf.maxy * maxyScaler + yConst
//				w = cf.w * wScaler + wConst
//				h = cf.h * hScaler + hConst
//
//-----------------------------------------------------------------------------
- drawSelf:(NXRect const*)cellFrame inView:aView
	{
	int const NUM_RECTS = 8;
	float const grays[ NUM_RECTS ] =
						{ NX_LTGRAY, NX_LTGRAY, NX_WHITE, NX_WHITE,
						  NX_BLACK, NX_BLACK, NX_DKGRAY, NX_DKGRAY };
	struct BC_Lines { char xs, maxxs, xc, ys, maxys, yc, ws, wc, hs, hc; };
	static BC_Lines const LINES[ NUM_RECTS ] =
		{
			{ 1, 0,	 0, 1, 0,  0, 0,  1, 1,	 0 }, // ltgray, left edge
			{ 1, 0,	 1, 1, 0,  0, 1, -1, 0,	 1 }, // ltgray, top edge
			{ 1, 0,	 1, 1, 0,  1, 0,  1, 1, -2 }, // white,	 left edge + 1
			{ 1, 0,	 2, 1, 0,  1, 1, -3, 0,	 1 }, // white,	 top edge + 1
			{ 0, 1, -1, 1, 0,  2, 0,  1, 1, -2 }, // black,	 right edge
			{ 1, 0,	 2, 0, 1, -1, 1, -3, 0,	 1 }, // black,	 bottom edge
			{ 1, 0,	 1, 0, 1, -1, 0,  1, 0,	 1 }, // dkgray, lower left corner
			{ 0, 1, -1, 1, 0,  1, 0,  1, 0,	 1 }  // dkgray, upper right corner
		};

	NXRect rects[ NUM_RECTS ];
	for (int i = 0; i < NUM_RECTS; i++)
		{
		BC_Lines const& r = LINES[i];
		NXSetRect( &(rects[i]),
				r.xs * NX_X(cellFrame) + r.maxxs * NX_MAXX(cellFrame) + r.xc,
				r.ys * NX_Y(cellFrame) + r.maxys * NX_MAXY(cellFrame) + r.yc,
				r.ws * NX_WIDTH(cellFrame) + r.wc,
				r.hs * NX_HEIGHT(cellFrame) + r.hc );
		}

	NXRectFillListWithGrays( rects, grays, NUM_RECTS );
	return [self drawInside:cellFrame inView:aView];
	}

@end
