/******************************************************************************
 * $Id: FilterBarButton.m 3083 2007-09-16 01:02:06Z livings124 $
 *
 * Copyright (c) 2006-2007 Transmission authors and contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *****************************************************************************/

#import "FilterBarButton.h"
#import "CTGradient.h"
#import "CTGradientAdditions.h"
#import "NSBezierPathAdditions.h"

@interface FilterBarButton (Private)

- (void) createPaths;
- (void) createGradients;
- (void) createFontAttributes;

@end

@implementation FilterBarButton

- (id) initWithCoder: (NSCoder *) coder
{
    if ((self = [super initWithCoder: coder]))
    {
        fEnabled = NO;
        fTrackingTag = 0;
        fCount = -1;
        [self setCount: 0];
        [self createPaths];
        [self createGradients];
        [self createFontAttributes];
        
        NSNotificationCenter * nc = [NSNotificationCenter defaultCenter];
        [nc addObserver: self selector: @selector(setForActive:) name: NSWindowDidBecomeKeyNotification object: [self window]];
        [nc addObserver: self selector: @selector(setForInactive:) name: NSWindowDidResignKeyNotification object: [self window]];
        [nc addObserver: self selector: @selector(resetBounds:) name: NSViewFrameDidChangeNotification object: nil];
    }
    return self;
}

- (void) dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver: self];

    [fPath release];
    [fEdgePath release];
    [fStepPath release];
    
    [fNormalAttributes release];
    [fNormalDimAttributes release];
    [fHighlightedAttributes release];
    
    [fHighlightedDimAttributes release];
    [fHighlightedBackground release];
    [fHighlightedOutline release];
    [fActiveBackground release];
    [fActiveOutline release];
    [fHoveringBackground release];
    [fHoveringOutline release];
    
    [super dealloc];
}

- (void) sizeToFit
{
    NSSize size = [[self title] sizeWithAttributes: fNormalAttributes];
    size.width = floorf(size.width + 14.5);
    size.height += 1;
    [self setFrameSize: size];
    [self setBoundsSize: size];
    [self createPaths];
}

- (BOOL) isFlipped
{
    return NO;
}

- (void) drawRect: (NSRect) rect
{
    // draw background
    if ([[self cell] isHighlighted])
    {
        [fHighlightedBackground fillBezierPath: fPath angle: -90.0];
        [fHighlightedOutline fillBezierPath: fStepPath angle: -90.0];
    }
    else
        switch (fState)
        {
            case 1:     // active
                [fActiveBackground fillBezierPath: fPath angle: -90.0];
                [fActiveOutline fillBezierPath: fStepPath angle: -90.0];
                break;
            case 2:     // hovering
            case 3:     // clicked but cell is not highlighted
                [fHoveringBackground fillBezierPath: fPath angle: -90.0];
                [fHoveringOutline setStroke];
                [fEdgePath stroke];
                break;
        }
    
    // draw title
    NSSize titleSize = [[self title] sizeWithAttributes: fNormalAttributes];
    NSPoint titlePos = NSMakePoint(([self bounds].size.width  - titleSize.width)  * 0.5,
                                   ([self bounds].size.height - titleSize.height) * 0.5 + 1.5);
    
    NSDictionary * attributes;
    if (fState)
        attributes = fEnabled ? fHighlightedAttributes : fHighlightedDimAttributes;
    else
        attributes = fEnabled ? fNormalAttributes : fNormalDimAttributes;
    
    [[self title] drawAtPoint: titlePos withAttributes: attributes];
}

- (void) setCount: (int) count
{
    if (count == fCount)
        return;
    fCount = count;
    
    [self setToolTip: fCount == 1 ? NSLocalizedString(@"1 Transfer", "Filter Bar Button -> tool tip")
            : [NSString stringWithFormat: NSLocalizedString(@"%d Transfers", "Filter Bar Button -> tool tip"), fCount]];
}

- (void) mouseDown: (NSEvent *) event
{
    if ([self state] != 1)
        [self setState: 3];
    [super mouseDown: event];
}

- (void) mouseUp: (NSEvent *) event
{
    [super mouseUp: event];
    if ([self state] != 1)
        [self setState: 1];
}

- (void) mouseEntered: (NSEvent *) event
{
    [super mouseEntered: event];
    if ([self state] == 0)
        [self setState: 2];
}

- (void) mouseExited: (NSEvent *) event
{
    [super mouseExited: event];
    if ([self state] >= 2)
        [self setState: 0];
}

- (void) setEnabled: (BOOL) enable
{
    fEnabled = enable;
    [self setNeedsDisplay: YES];
}

- (int) state
{
    return fState;
}

- (void) setState: (int) state
{
    fState = state;
    [self setNeedsDisplay: YES];
}

- (void) resetBounds: (NSNotification *) notification
{
    if (fTrackingTag)
        [self removeTrackingRect: fTrackingTag];
    fTrackingTag = [self addTrackingRect: [self bounds] owner: self userData: nil assumeInside: NO];
}

- (void) setForActive: (NSNotification *) notification
{
    [self setEnabled: YES];
    [self resetBounds: nil];
    [self setNeedsDisplay: YES];
}

- (void) setForInactive: (NSNotification *) notification
{
    if (fTrackingTag)
    {
        [self removeTrackingRect: fTrackingTag];
        fTrackingTag = 0;
    }
    [self setEnabled: NO];
    [self setNeedsDisplay: YES];
}

@end

@implementation FilterBarButton (Private)

- (void) createPaths
{
    NSSize buttonSize = [self frame].size;
    
    // the main button path
    [fPath release];
    fPath = [[NSBezierPath bezierPathWithRoundedRect: NSMakeRect(0.0, 1.0, buttonSize.width, buttonSize.height - 1.0)
                radius: (buttonSize.height - 1.0) / 2.0] retain];
    
    // the path used to draw the hover edging
    [fEdgePath release];
    fEdgePath = [[NSBezierPath bezierPathWithRoundedRect: NSMakeRect(0.5, 1.5, buttonSize.width - 1.0, buttonSize.height - 2.0)
                    radius: (buttonSize.height - 2.0) / 2.0] retain];
    
    // the path used to draw the depressed shading/highlights of the active button
    [fStepPath release];
    fStepPath = [[NSBezierPath bezierPathWithRoundedRect: NSMakeRect(0.0, 0.0, buttonSize.width, buttonSize.height - 1.0)
                    radius: (buttonSize.height - 1.0) / 2.0] retain];
    [fStepPath appendBezierPath: fPath];
    [fStepPath setWindingRule: NSEvenOddWindingRule];
}

- (void) createGradients
{
    NSColor *quarterAlphaBlack = [NSColor colorWithCalibratedWhite: 0.0 alpha: 0.25];
    NSColor *thirdAlphaWhite = [NSColor colorWithCalibratedWhite: 1.0 alpha: 0.3333];
    fHighlightedBackground = [[CTGradient gradientWithBeginningColor: [NSColor colorWithCalibratedRed: 134.0/255 green: 151.0/255 blue: 176.0/255 alpha: 1.0]
                                                         endingColor: [NSColor colorWithCalibratedRed: 104.0/255 green: 125.0/255 blue: 157.0/255 alpha: 1.0]] retain];
    fHighlightedOutline = [[CTGradient gradientWithBeginningColor: quarterAlphaBlack
                                                     middleColor1: quarterAlphaBlack
                                                     middleColor2: thirdAlphaWhite
                                                      endingColor: thirdAlphaWhite] retain];
    fActiveBackground = [[CTGradient gradientWithBeginningColor: [NSColor colorWithCalibratedRed: 151.0/255 green: 166.0/255 blue: 188.0/255 alpha: 1.0]
                                                    endingColor: [NSColor colorWithCalibratedRed: 126.0/255 green: 144.0/255 blue: 171.0/255 alpha: 1.0]] retain];
    fActiveOutline = [fHighlightedOutline retain];
    fHoveringBackground = [[CTGradient gradientWithBeginningColor: [NSColor colorWithCalibratedRed: 164.0/255 green: 177.0/255 blue: 196.0/255 alpha: 1.0]
                                                      endingColor: [NSColor colorWithCalibratedRed: 141.0/255 green: 158.0/255 blue: 182.0/255 alpha: 1.0]] retain];
    fHoveringOutline = [[NSColor colorWithCalibratedWhite: 0.0 alpha: 0.075] retain];
}

- (void) createFontAttributes
{
    NSFont * boldSystemFont = [NSFont boldSystemFontOfSize: 12.0];
    NSSize shadowOffset = NSMakeSize(0.0, -1.0);
    
    NSShadow * shadowNormal = [[[NSShadow alloc] init] autorelease]; 
    [shadowNormal setShadowOffset: shadowOffset]; 
    [shadowNormal setShadowBlurRadius: 1.0]; 
    [shadowNormal setShadowColor: [NSColor colorWithCalibratedWhite: 1.0 alpha: 0.4]]; 
    
    NSShadow * shadowNormalDim = [[[NSShadow alloc] init] autorelease]; 
    [shadowNormalDim setShadowOffset: shadowOffset]; 
    [shadowNormalDim setShadowBlurRadius: 1.0]; 
    [shadowNormalDim setShadowColor: [NSColor colorWithCalibratedWhite: 1.0 alpha: 0.2]]; 
    
    NSShadow * shadowHighlighted = [[[NSShadow alloc] init] autorelease]; 
    [shadowHighlighted setShadowOffset: shadowOffset]; 
    [shadowHighlighted setShadowBlurRadius: 1.0]; 
    [shadowHighlighted setShadowColor: [NSColor colorWithCalibratedWhite: 0.0 alpha: 0.4]]; 
    
    fNormalAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
        [NSColor colorWithCalibratedWhite: 0.259 alpha: 1.0], NSForegroundColorAttributeName,
        boldSystemFont, NSFontAttributeName,
        shadowNormal, NSShadowAttributeName, nil];
    
    fNormalDimAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
        [NSColor disabledControlTextColor], NSForegroundColorAttributeName,
        boldSystemFont, NSFontAttributeName,
        shadowNormalDim, NSShadowAttributeName, nil];
    
    fHighlightedAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
        [NSColor whiteColor], NSForegroundColorAttributeName,
        boldSystemFont, NSFontAttributeName,
        shadowHighlighted, NSShadowAttributeName, nil];
    
    fHighlightedDimAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
        [NSColor colorWithCalibratedWhite: 0.9 alpha: 1.0], NSForegroundColorAttributeName,
        boldSystemFont, NSFontAttributeName,
        shadowHighlighted, NSShadowAttributeName, nil];
}

@end
