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