//
//  DKButtonCell.m
//  DarkKit
//
//  Created by Chad Weider on 4/7/07.
//  Copyright (c) 2008 Chad Weider
//  Some rights reserved: <http://www.opensource.org/licenses/zlib-license.php>
//  
//  This software is provided 'as-is', without any express or implied warranty.
//  In no event will the authors be held liable for any damages arising from the
//  use of this software.
//  
//  Permission is granted to anyone to use this software for any purpose,
//  including commercial applications, and to alter it and redistribute it
//  freely, subject to the following restrictions:
//  
//  1. The origin of this software must not be misrepresented; you must not   
//  claim that you wrote the original software. If you use this software in a
//  product, an acknowledgment in the product documentation would be appreciated
//  but is not required.
//  
//  2. Altered source versions must be plainly marked as such, and must not be
//  misrepresented as being the original software.
//  
//  3. This notice may not be removed or altered from any source distribution.
//

#import "DKButtonCell.h"

#import "NSBezierPath+PXRoundedRectangleAdditions.h"
#import "CTGradient.h"

@interface NSButtonCell (NSButtonCellPrivate)
- (NSDictionary *)_textAttributes;
- (int)_buttonType;
@end

@implementation DKButtonCell

- (void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView
  {
  if([self bezelStyle] == NSRoundedBezelStyle)
	{
	NSRect buttonRect;
	float buttonHeight;
	float buttonXPad;
	float buttonYShift;
	float buttonBoxHeight;
	float cornerRadius = NSHeight(frame)/2;
	
	switch([self controlSize])
		{
		case NSRegularControlSize:
			buttonXPad = 7;
			buttonYShift = 1;
			buttonBoxHeight = 25;
			buttonHeight = 20;
							break;
		case NSSmallControlSize:
			buttonXPad = 5;
			buttonYShift = 1;
			buttonBoxHeight = 21;
			buttonHeight = 17;
							break;
		case NSMiniControlSize:
			buttonXPad = 2;
			buttonYShift = 1;
			buttonBoxHeight = 17;
			buttonHeight = 14;
							break;
		}
	buttonRect = NSMakeRect(frame.origin.x+buttonXPad+.5, floorf(NSMidY(frame)-(buttonBoxHeight)/2)+buttonYShift+.5, frame.size.width-2*buttonXPad, buttonHeight);
	NSBezierPath *bezelPath = [NSBezierPath bezierPathWithRoundedRect:buttonRect cornerRadius:cornerRadius];
	
    CTGradient *fillGradient;
	if(([self isHighlighted] && ([self highlightsBy] & (NSChangeGrayCellMask | NSChangeBackgroundCellMask | NSPushInCellMask))) ||
	   ([self state] == NSOnState && ([self showsStateBy] & (NSChangeGrayCellMask | NSChangeBackgroundCellMask | NSPushInCellMask))))
		fillGradient = [CTGradient gradientWithBeginningColor:[NSColor colorWithCalibratedWhite:.4 alpha:1.0]
                                                  endingColor:[NSColor colorWithCalibratedWhite:.2 alpha:1.0]];
	else
        fillGradient = [CTGradient gradientWithBeginningColor:[NSColor colorWithCalibratedWhite:.3 alpha:1.0]
                                                  endingColor:[NSColor colorWithCalibratedWhite:.0 alpha:1.0]];
    
	[fillGradient fillBezierPath:bezelPath angle:90.0];

	[bezelPath setLineWidth:1];
	[[NSColor colorWithCalibratedWhite:1 alpha:1] set];
	[bezelPath stroke];
	}
	
	
	
  else if([self bezelStyle] == NSSmallSquareBezelStyle)
	{
	NSRect buttonRect = NSInsetRect(frame, 0, 1);
    [[NSColor whiteColor] set];
    NSRectFill(buttonRect);
    
    CTGradient *fillGradient = [[[CTGradient alloc] init] autorelease];
	
    if([self isHighlighted] && ([self highlightsBy] & NSPushInCellMask))
		{
        fillGradient = [fillGradient addColorStop:[NSColor colorWithCalibratedWhite:.40 alpha:1.0] atPosition:.5];
        fillGradient = [fillGradient addColorStop:[NSColor colorWithCalibratedWhite:.30 alpha:1.0] atPosition:.5];
        }
	else if([self state] == NSOnState && ([self highlightsBy] & NSChangeBackgroundCellMask))
		{
        fillGradient = [fillGradient addColorStop:[NSColor colorWithCalibratedWhite:.32 alpha:1.0] atPosition:.5];
        fillGradient = [fillGradient addColorStop:[NSColor colorWithCalibratedWhite:.22 alpha:1.0] atPosition:.5];
        }
    else
		{
        fillGradient = [fillGradient addColorStop:[NSColor colorWithCalibratedWhite:.15 alpha:1.0] atPosition:.5];
        fillGradient = [fillGradient addColorStop:[NSColor colorWithCalibratedWhite:.05 alpha:1.0] atPosition:.5];
        }
    
    [fillGradient fillRect:NSInsetRect(buttonRect, 1, 1) angle:90];
    }
	
	
	
  else if([self bezelStyle] == NSShadowlessSquareBezelStyle)
	{
	NSRect buttonRect = frame;
    [[NSColor colorWithCalibratedWhite:.25 alpha:1.0] set];
    NSRectFill(buttonRect);
    
    CTGradient *fillGradient;
    
    if([self isHighlighted] && ([self highlightsBy] & NSPushInCellMask))
		{
        fillGradient = [CTGradient gradientWithBeginningColor:[NSColor colorWithCalibratedWhite:.27 alpha:1.0]
                                                  endingColor:[NSColor colorWithCalibratedWhite:.37 alpha:1.0]];
        }
    else if([self state] == NSOnState && ([self highlightsBy] & NSChangeBackgroundCellMask))
        {
        fillGradient = [CTGradient gradientWithBeginningColor:[NSColor colorWithCalibratedWhite:.23 alpha:1.0]
                                                  endingColor:[NSColor colorWithCalibratedWhite:.33 alpha:1.0]];
        }
    else
		{
        fillGradient = [CTGradient gradientWithBeginningColor:[NSColor colorWithCalibratedWhite:.08 alpha:1.0]
                                                  endingColor:[NSColor colorWithCalibratedWhite:.18 alpha:1.0]];
        }
    
    buttonRect = NSInsetRect(buttonRect, 1, 1);
    [fillGradient fillRect:buttonRect angle:90];
    
    CTGradient *highlightGradient = [CTGradient gradientWithBeginningColor:[NSColor colorWithCalibratedWhite:1 alpha:.2]
                                                               endingColor:[NSColor colorWithCalibratedWhite:1 alpha:.0]];
    NSRect highlightRect;
    NSRect remainderRect;
    NSDivideRect(buttonRect, &highlightRect, &remainderRect, 2.5, NSMinYEdge);
    [highlightGradient fillRect:highlightRect angle:90];
    
    CTGradient *shadowGradient = [CTGradient gradientWithBeginningColor:[NSColor colorWithCalibratedWhite:0 alpha:.4]
                                                               endingColor:[NSColor colorWithCalibratedWhite:.0 alpha:.00]];
    NSRect shadowRect;
    NSDivideRect(buttonRect, &shadowRect, &remainderRect, 2, NSMinXEdge);
    [shadowGradient fillRect:shadowRect angle:0];
    NSDivideRect(buttonRect, &shadowRect, &remainderRect, 2, NSMaxXEdge);
    [shadowGradient fillRect:shadowRect angle:-180];
    NSDivideRect(buttonRect, &shadowRect, &remainderRect, 2.5, NSMaxYEdge);
    [shadowGradient fillRect:shadowRect angle:-90];
    }
  }

- (void)drawImage:(NSImage *)image withFrame:(NSRect)frame inView:(NSView *)controlView
  {
  if([self _buttonType] == NSSwitchButton)
	{
	float pad;
	float checkOffX,checkOffY;
	float cornerRadius = 2;
	NSRect buttonRect;
	
	switch([self controlSize])
		{
		case NSRegularControlSize:
			pad = 2;
			checkOffX = 2.5;
			checkOffY = 4;
							break;
		case NSSmallControlSize:
			pad = 3;
			checkOffX = 2.5;
			checkOffY = 4;
							break;
		case NSMiniControlSize:
			pad = 4;
			checkOffX = 1.5;
			checkOffY = 2.5;
							break;
		}
	
	buttonRect = NSInsetRect(frame,pad+.5,pad+.5);
	NSBezierPath *bezelPath = [NSBezierPath bezierPathWithRoundedRect:buttonRect cornerRadius:cornerRadius];

	float dim = 0;
	if([self isHighlighted])
		dim = 1;
	
	NSColor *startColor = [NSColor colorWithCalibratedWhite:(dim ? .4 : .3) alpha:([self isEnabled] ? 1 : .5)];
	NSColor *endColor = [NSColor colorWithCalibratedWhite:(dim ? .2: 0) alpha:([self isEnabled] ? 1 : .5)];
	CTGradient *backgroundGradient = [CTGradient gradientWithBeginningColor:startColor endingColor:endColor];
	[backgroundGradient fillBezierPath:bezelPath angle:90.0];
	
	[bezelPath setLineWidth:1];
	[[NSColor colorWithCalibratedWhite:1 alpha:([self isEnabled] ? 1 : .5)] set];
	[bezelPath stroke];
	
	
	//Draw Check
	if([self state] == NSOnState)
		{
		NSRect checkRect = NSOffsetRect(buttonRect, checkOffX, -checkOffY);
		NSBezierPath *checkPath = [[NSBezierPath alloc] init];
		
		[checkPath moveToPoint:NSMakePoint(NSMinX(checkRect), NSMidY(checkRect)+1)];
		[checkPath lineToPoint:NSMakePoint(NSMinX(checkRect) + NSWidth(checkRect)*.3, NSMaxY(checkRect))];
		[checkPath lineToPoint:NSMakePoint(NSMinX(checkRect) + NSWidth(checkRect)*.8, NSMinY(checkRect)+1)];
		
		[[NSColor colorWithCalibratedWhite:0.75 alpha:([self isEnabled] ? 1 : .5)] set];
		[checkPath setLineWidth:2];
		[checkPath setLineJoinStyle:NSMiterLineJoinStyle];
		[checkPath stroke];
		}
    //Draw Dash
	else if([self state] == NSMixedState)
		{
		NSRect checkRect = NSIntegralRect(NSInsetRect(buttonRect, NSWidth(buttonRect)*.30, NSHeight(buttonRect)*.45));
		
		[[NSColor colorWithCalibratedWhite:0.75 alpha:([self isEnabled] ? 1 : .5)] set];
		NSRectFill(checkRect);
		}
	}

  else if([self _buttonType] == NSRadioButton)
    {
    float pad;
	float checkOffX,checkOffY;
	NSRect buttonRect;
	
	switch([self controlSize])
		{
		case NSRegularControlSize:
			pad = 2;
			checkOffX = 2.5;
			checkOffY = 4;
							break;
		case NSSmallControlSize:
			pad = 3;
			checkOffX = 2.5;
			checkOffY = 4;
							break;
		case NSMiniControlSize:
			pad = 4;
			checkOffX = 1.5;
			checkOffY = 2.5;
							break;
		}
    
    buttonRect = NSInsetRect(frame,pad+.5,pad+.5);
	NSBezierPath *bezelPath = [NSBezierPath bezierPathWithOvalInRect:buttonRect];

	float dim = 0;
	if([self isHighlighted] && !([self state] == NSOnState))
		dim = 1;
	
	NSColor *startColor = [NSColor colorWithCalibratedWhite:(dim ? .4 : .3) alpha:([self isEnabled] ? 1 : .5)];
	NSColor *endColor = [NSColor colorWithCalibratedWhite:(dim ? .2: 0) alpha:([self isEnabled] ? 1 : .5)];
	CTGradient *backgroundGradient = [CTGradient gradientWithBeginningColor:startColor endingColor:endColor];
	[backgroundGradient fillBezierPath:bezelPath angle:90.0];
	
	[bezelPath setLineWidth:1];
	[[NSColor colorWithCalibratedWhite:1 alpha:([self isEnabled] ? 1 : .5)] set];
	[bezelPath stroke];
    
    //Draw Dot
	if([self state] == NSOnState)
		{
		NSBezierPath *checkPath = [NSBezierPath bezierPathWithOvalInRect:NSMakeRect(NSMidX(buttonRect)-2, NSMidY(buttonRect)-2, 4, 4)];
        		
		[[NSColor colorWithCalibratedWhite:0.85 alpha:([self isEnabled] ? 1 : .5)] set];
		[checkPath fill];
		}
    //Draw Dash
	else if([self state] == NSMixedState)
		{
		NSRect checkRect = NSIntegralRect(NSInsetRect(buttonRect, NSWidth(buttonRect)*.30, NSHeight(buttonRect)*.45));
		
		[[NSColor colorWithCalibratedWhite:0.75 alpha:([self isEnabled] ? 1 : .5)] set];
		NSRectFill(checkRect);
		}
    }
  else
    [super drawImage:image withFrame:frame inView:controlView];
  }



- (NSDictionary *)_textAttributes
  {
  NSMutableDictionary *aDict = [[NSMutableDictionary alloc] init];
  [aDict addEntriesFromDictionary:[super _textAttributes]];
  [aDict setObject:[NSColor colorWithCalibratedWhite:DKTextWhite alpha:1] forKey:NSForegroundColorAttributeName];
  
  return [aDict autorelease];
  }

@end
