1/******************************************************************************
2 * $Id: StatusBarView.m 13563 2012-10-14 17:33:23Z livings124 $
3 * 
4 * Copyright (c) 2006-2012 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#import "StatusBarView.h"
26#import "NSApplicationAdditions.h"
27#import <QuartzCore/QuartzCore.h>
28
29@interface StatusBarView (Private)
30
31- (void) reload;
32
33@end
34
35@implementation StatusBarView
36
37- (id) initWithFrame: (NSRect) rect
38{
39    if ((self = [super initWithFrame: rect]))
40    {
41        NSColor * lightColor = [NSColor colorWithCalibratedRed: 160.0/255.0 green: 160.0/255.0 blue: 160.0/255.0 alpha: 1.0];
42        NSColor * darkColor = [NSColor colorWithCalibratedRed: 155.0/255.0 green: 155.0/255.0 blue: 155.0/255.0 alpha: 1.0];
43        fGradient = [[NSGradient alloc] initWithStartingColor: lightColor endingColor: darkColor];
44        
45        if([NSApp isOnLionOrBetter])
46        {
47            CIFilter * randomFilter = [CIFilter filterWithName: @"CIRandomGenerator"];
48            [randomFilter setDefaults];
49            
50            fNoiseImage = [randomFilter valueForKey: @"outputImage"];
51            
52            CIFilter * monochromeFilter = [CIFilter filterWithName: @"CIColorMonochrome"];
53            [monochromeFilter setDefaults];
54            [monochromeFilter setValue: fNoiseImage forKey: @"inputImage"];
55            CIColor * monoFilterColor = [CIColor colorWithRed: 1.0 green: 1.0 blue: 1.0];
56            [monochromeFilter setValue: monoFilterColor forKey: @"inputColor"];
57            fNoiseImage = [[monochromeFilter valueForKey:@"outputImage"] retain];
58        }
59        else
60            fNoiseImage = nil;
61        
62        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(reload) name: NSWindowDidBecomeMainNotification object: [self window]];
63        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(reload) name: NSWindowDidResignMainNotification object: [self window]];
64    }
65    return self;
66}
67
68- (void) dealloc
69{
70    [[NSNotificationCenter defaultCenter] removeObserver: self];
71    [fNoiseImage release];
72    [fGradient release];
73    [super dealloc];
74}
75
76- (BOOL) mouseDownCanMoveWindow
77{
78    return YES;
79}
80
81- (BOOL) isOpaque
82{
83    return YES;
84}
85
86- (void) drawRect: (NSRect) rect
87{
88    const BOOL active = [[self window] isMainWindow];
89    
90    NSInteger count = 0;
91    NSRect gridRects[active ? 2 : 3];
92    NSColor * colorRects[active ? 2 : 3];
93    
94    //bottom line
95    NSRect lineBorderRect = NSMakeRect(NSMinX(rect), 0.0, NSWidth(rect), 1.0);
96    NSRect intersectLineBorderRect = NSIntersectionRect(lineBorderRect, rect);
97    if (!NSIsEmptyRect(intersectLineBorderRect))
98    {
99        gridRects[count] = intersectLineBorderRect;
100        colorRects[count] = active ? [NSColor colorWithCalibratedWhite: 0.25 alpha: 1.0]
101        : [NSColor colorWithCalibratedWhite: 0.5 alpha: 1.0];
102        ++count;
103        
104        rect.origin.y += intersectLineBorderRect.size.height;
105        rect.size.height -= intersectLineBorderRect.size.height;
106    }
107    
108    
109    //top line
110    if (active)
111    {
112        lineBorderRect.origin.y = NSHeight([self bounds]) - 1.0;
113        intersectLineBorderRect = NSIntersectionRect(lineBorderRect, rect);
114        if (!NSIsEmptyRect(intersectLineBorderRect))
115        {
116            gridRects[count] = intersectLineBorderRect;
117            colorRects[count] = [NSColor colorWithCalibratedWhite: 0.75 alpha: 1.0];
118            ++count;
119            
120            rect.size.height -= intersectLineBorderRect.size.height;
121        }
122    }
123    
124    if (!NSIsEmptyRect(rect))
125    {
126        if (active)
127        {
128            const NSRect gradientRect = NSMakeRect(NSMinX(rect), 1.0, NSWidth(rect), NSHeight([self bounds]) - 1.0 - 1.0); //proper gradient requires the full height of the bar
129            [fGradient drawInRect: gradientRect angle: 270.0];
130        }
131        else
132        {
133            gridRects[count] = rect;
134            colorRects[count] = [NSColor colorWithCalibratedWhite: 0.85 alpha: 1.0];
135            ++count;
136        }
137    }
138    
139    NSRectFillListWithColors(gridRects, colorRects, count);
140    
141    if (fNoiseImage) {
142        NSAssert([NSApp isOnLionOrBetter], @"we have a noise image, but we're on 10.6"); //https://trac.transmissionbt.com/ticket/5053
143        [fNoiseImage drawInRect: rect
144                       fromRect: [self convertRectToBacking: rect]
145                      operation: NSCompositeSourceOver
146                       fraction: 0.12];
147    }
148}
149
150@end
151
152@implementation StatusBarView (Private)
153
154- (void) reload
155{
156    [self setNeedsDisplay: YES];
157}
158
159@end
160