transmission/macosx/FilterBarButton.m

301 lines
11 KiB
Objective-C

/******************************************************************************
* $Id$
*
* 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 "BezierPathAdditions.h"
@interface FilterBarButton (Private)
- (void) createPaths;
- (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 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];
[super dealloc];
}
- (void)sizeToFit
{
NSSize size = [[self title] sizeWithAttributes: fNormalAttributes];
size.width = floorf(size.width + 18.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])
{
[[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]]
fillBezierPath: fPath angle: -90.0];
[[CTGradient gradientWithBeginningColor: [NSColor colorWithCalibratedWhite: 0.0 alpha: 0.25]
// middleColor: [NSColor colorWithCalibratedWhite: 0.5 alpha: 0.00]
middleColor1: [NSColor colorWithCalibratedWhite: 0.0 alpha: 0.25]
middleColor2: [NSColor colorWithCalibratedWhite: 1.0 alpha: 0.50]
endingColor: [NSColor colorWithCalibratedWhite: 1.0 alpha: 0.50]]
fillBezierPath: fStepPath angle: -90.0];
}
else switch (fState)
{
case 1: // active
[[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]]
fillBezierPath: fPath angle: -90.0];
[[CTGradient gradientWithBeginningColor: [NSColor colorWithCalibratedWhite: 0.0 alpha: 0.25]
// middleColor: [NSColor colorWithCalibratedWhite: 0.5 alpha: 0.00]
middleColor1: [NSColor colorWithCalibratedWhite: 0.0 alpha: 0.25]
middleColor2: [NSColor colorWithCalibratedWhite: 1.0 alpha: 0.50]
endingColor: [NSColor colorWithCalibratedWhite: 1.0 alpha: 0.50]]
fillBezierPath: fStepPath angle: -90.0];
break;
case 2: // hovering
[[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]]
fillBezierPath: fPath angle: -90.0];
[[NSColor colorWithCalibratedWhite: 0.0 alpha: 0.075] set];
[fEdgePath stroke];
break;
case 3: // clicked but cell is not highlighted
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);
if (fEnabled)
{
if (fState && !(fState == 3 && ![[self cell] isHighlighted]))
[[self title] drawAtPoint: titlePos withAttributes: fHighlightedAttributes];
else
[[self title] drawAtPoint: titlePos withAttributes: fNormalAttributes];
}
else
{
if (fState)
[[self title] drawAtPoint: titlePos withAttributes: fHighlightedDimAttributes];
else
[[self title] drawAtPoint: titlePos withAttributes: fNormalDimAttributes];
}
}
- (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) 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