//=============================================================================
//
//	Copyright (C) 1995-1997 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.6 97/03/23 05:45:38 sunshine Exp $
// $Log:	MiscBorderCell.M,v $
//  Revision 1.6  97/03/23  05:45:38  sunshine
//  v125.4: Worked around OPENSTEP 4.1 bug where -setupFieldEditorAttributes:
//  never gets called, so text was not drawing white.  Worked around problem by
//  subclassing from NSTextFieldCell rather than NSCell.  This way color can
//  be set with -setTextColor:.
//  
//  Revision 1.5  96/12/30  06:27:08  sunshine
//  v105.1: Added the image instance variable, and support for drawing it.
//  
//  Revision 1.4  96/05/07  02:09:40  sunshine
//  Rewrote -drawSelf:inView: so that it makes only 1 trip to Window Server
//  instead of 8, and is now table driven.
//-----------------------------------------------------------------------------
#import "MiscBorderCell.h"
extern "Objective-C" {
#import <AppKit/NSFont.h>
#import <AppKit/NSImage.h>
}
extern "C" {
#import	<math.h>
}

int const BORDER_TOP	= 2;	// 2 pixels for top    border
int const BORDER_BOTTOM	= 1;	// 1 pixel  for bottom border
int const BORDER_LEFT	= 2;	// 2 pixels for left   border
int const BORDER_RIGHT	= 1;	// 1 pixel  for right  border

int const BORDER_WIDTH	= (BORDER_LEFT + BORDER_RIGHT);
int const BORDER_HEIGHT	= (BORDER_TOP + BORDER_BOTTOM);

int const RESIZE_WIDTH	= 3;	// Resize zone is 4 pixels on right.

@implementation MiscBorderCell

//-----------------------------------------------------------------------------
// -setImage:
//-----------------------------------------------------------------------------
- (void)setImage:(NSImage*)p
    {
    [image autorelease];
    image = [p retain];
    }


//-----------------------------------------------------------------------------
// -initTextCell:
//-----------------------------------------------------------------------------
- (id)initTextCell:(NSString*)s
    {
    [super initTextCell:s];
    [self setBordered:NO];
    [self setWraps:NO];
    [self setAlignment:NSCenterTextAlignment];
    [self setFont:[NSFont boldSystemFontOfSize:12.0]];
    [self setTextColor:[NSColor whiteColor]];
    return self;
    }


//-----------------------------------------------------------------------------
// -backgroundColor
//-----------------------------------------------------------------------------
- (NSColor*)backgroundColor
    {
    NSColor* c = [NSColor darkGrayColor];
    if ([self state])
	c = [c blendedColorWithFraction:0.5 ofColor:[NSColor blackColor]];
    return c;
    }


//-----------------------------------------------------------------------------
// -cellSizeForBounds:
//-----------------------------------------------------------------------------
- (NSSize)cellSizeForBounds:(NSRect)aRect
    {
    NSSize s = [super cellSizeForBounds:aRect];
    s.width += BORDER_WIDTH + RESIZE_WIDTH;
    s.height += BORDER_HEIGHT;
    if (image != 0)
	s.width += [image size].width;
    return s;
    }


//-----------------------------------------------------------------------------
// -drawInteriorWithFrame:inView:
//-----------------------------------------------------------------------------
- (void)drawInteriorWithFrame:(NSRect)p inView:(NSView*)v
    {
    // Assume the view is flipped.
    [[self backgroundColor] set];
    NSRect r = NSMakeRect(  NSMinX(p) + BORDER_LEFT, NSMinY(p) + BORDER_TOP,
		NSWidth(p) - BORDER_WIDTH, NSHeight(p) - BORDER_HEIGHT );
    NSRectFill( r );

    if (image != 0)
	{
	NSSize sz = [image size];

	NSPoint pt;
	pt.x = NSMaxX(p) - BORDER_RIGHT - RESIZE_WIDTH;
	pt.y = NSMaxY(p) - BORDER_BOTTOM;

	float max_height = floor( NSHeight(p) - BORDER_HEIGHT );
	float max_width = floor( NSWidth(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)
	    {
	    NSRect 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 compositeToPoint:pt fromRect:q
				operation:NSCompositeSourceOver];
	    }
	else
	    {
	    // Center image vertically.
	    pt.y = floor( pt.y - ((max_height - sz.height) / 2) );
	    pt.x -= sz.width;
	    [image compositeToPoint:pt operation:NSCompositeSourceOver];
	    }

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

    [super drawInteriorWithFrame:r inView:v];
    }


//-----------------------------------------------------------------------------
// -drawWithFRame: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
//
//-----------------------------------------------------------------------------
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)aView
    {
    int const NUM_RECTS = 8;
    float const grays[ NUM_RECTS ] =
			{ NSLightGray, NSLightGray, NSWhite, NSWhite,
			  NSBlack, NSBlack, NSDarkGray, NSDarkGray };
    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
	};

    NSRect rects[ NUM_RECTS ];
    for (int i = 0; i < NUM_RECTS; i++)
	{
	BC_Lines const& r = LINES[i];
	rects[i] = NSMakeRect(
		r.xs * NSMinX(cellFrame) + r.maxxs * NSMaxX(cellFrame) + r.xc,
		r.ys * NSMinY(cellFrame) + r.maxys * NSMaxY(cellFrame) + r.yc,
		r.ws * NSWidth(cellFrame) + r.wc,
		r.hs * NSHeight(cellFrame) + r.hc );
	}

    NSRectFillListWithGrays( rects, grays, NUM_RECTS );
    [self drawInteriorWithFrame:cellFrame inView:aView];
    }

@end
