b9e8c938276ecf7a1fb5b335b0bc7ce0a4de59c1
[vlc.git] / modules / gui / macosx / VLCHUDCheckboxCell.m
1 //
2 //  VLCHUDCheckboxCell.m
3 //  BGHUDAppKit
4 //
5 //  Created by BinaryGod on 5/25/08.
6 //
7 //  Copyright (c) 2008, Tim Davis (BinaryMethod.com, binary.god@gmail.com)
8 //  All rights reserved.
9 //
10 //  Redistribution and use in source and binary forms, with or without modification,
11 //  are permitted provided that the following conditions are met:
12 //
13 //              Redistributions of source code must retain the above copyright notice, this
14 //      list of conditions and the following disclaimer.
15 //
16 //              Redistributions in binary form must reproduce the above copyright notice,
17 //      this list of conditions and the following disclaimer in the documentation and/or
18 //      other materials provided with the distribution.
19 //
20 //              Neither the name of the BinaryMethod.com nor the names of its contributors
21 //      may be used to endorse or promote products derived from this software without
22 //      specific prior written permission.
23 //
24 //      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND
25 //      ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 //      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 //      IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28 //      INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 //      BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
30 //      OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 //      WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 //      ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 //      POSSIBILITY OF SUCH DAMAGE.
34
35 #import "VLCHUDCheckboxCell.h"
36 #import "CompatibilityFixes.h"
37
38 @implementation VLCHUDCheckboxCell
39
40 + (void)load
41 {
42     /* On 10.10+ we do not want custom drawing, therefore we swap out the implementation
43      * of the selectors below with their original implementations.
44      * Just calling super will not work, as the AppKit implementation for the NSButton
45      * checkbox checks if the drawing related selectors below are overriden, and if
46      * that is the case, will fall back to legacy drawing, without animation,
47      * without vibrancy and non-layer-based.
48      */
49     if (OSX_YOSEMITE_AND_HIGHER) {
50         swapoutOverride([VLCHUDCheckboxCell class], @selector(initWithCoder:));
51         swapoutOverride([VLCHUDCheckboxCell class], @selector(drawImage:withFrame:inView:));
52         swapoutOverride([VLCHUDCheckboxCell class], @selector(drawTitle:withFrame:inView:));
53     }
54 }
55
56 - (instancetype)initWithCoder:(NSCoder *)coder
57 {
58     self = [super initWithCoder:coder];
59     if (self) {
60         /* Colors */
61         _cellTextColor         = [NSColor whiteColor];
62         _disabledCellTextColor = [NSColor colorWithCalibratedWhite:1.0f alpha:0.5f];
63         _strokeColor           = [NSColor whiteColor];
64         _disabledStrokeColor   = [NSColor colorWithCalibratedWhite:1.0f alpha:0.5f];
65
66         /* Gradients */
67         _normalGradient    = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceRed:0.251f green:0.251f blue:0.255f alpha:1.0f]
68                                                            endingColor:[NSColor colorWithDeviceRed:0.118f green:0.118f blue:0.118f alpha:1.0f]];
69         _highlightGradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceRed:0.451f green:0.451f blue:0.455f alpha:1.0f]
70                                                            endingColor:[NSColor colorWithDeviceRed:0.318f green:0.318f blue:0.318f alpha:1.0f]];
71         _pushedGradient    = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceRed:0.451f green:0.451f blue:0.455f alpha:1.0f]
72                                                            endingColor:[NSColor colorWithDeviceRed:0.318f green:0.318f blue:0.318f alpha:1.0f]];
73     }
74     return self;
75 }
76
77 - (void)drawImage:(NSImage *)image withFrame:(NSRect)frame inView:(NSView *)controlView
78 {
79     // Set frame size correctly
80     NSRect backgroundFrame = frame;
81     if (self.controlSize == NSSmallControlSize) {
82         frame.origin.x += 4;
83         frame.origin.y += 2.5;
84         frame.size.width -= 5;
85         frame.size.height -= 5;
86         backgroundFrame = NSInsetRect(frame, 1.5, 1.5);
87     } else if (self.controlSize == NSMiniControlSize) {
88         frame.origin.x += 2.5;
89         frame.origin.y += 4;
90         frame.size.width -= 5;
91         frame.size.height -= 5;
92         backgroundFrame = NSInsetRect(frame, 2, 2);
93     }
94
95     // Set fill frame
96     NSBezierPath *backgroundPath = [NSBezierPath bezierPathWithRoundedRect:backgroundFrame
97                                                                    xRadius:2
98                                                                    yRadius:2];
99
100     // Draw background and stroke
101     if([self isEnabled]) {
102         if ([self isHighlighted]) {
103             [_highlightGradient drawInBezierPath:backgroundPath angle:90.0];
104         } else {
105             [_normalGradient drawInBezierPath:backgroundPath angle:90.0];
106         }
107         [_strokeColor setStroke];
108     } else {
109         [_disabledStrokeColor setStroke];
110     }
111
112     [NSGraphicsContext saveGraphicsState];
113     if ([super showsFirstResponder] && [[[self controlView] window] isKeyWindow] &&
114        ([self focusRingType] == NSFocusRingTypeDefault ||
115         [self focusRingType] == NSFocusRingTypeExterior)) {
116         NSSetFocusRingStyle(NSFocusRingOnly);
117     }
118     [backgroundPath setLineWidth:1.0];
119     [backgroundPath stroke];
120     [NSGraphicsContext restoreGraphicsState];
121
122     // Now drawing tick
123     if ([self intValue]) {
124         NSBezierPath* bezierPath = [NSBezierPath bezierPath];
125         [bezierPath moveToPoint: NSMakePoint(NSMinX(frame) + 3.0, NSMidY(frame) - 2.0)];
126         [bezierPath lineToPoint: NSMakePoint(NSMidX(frame), NSMidY(frame) + 2.0)];
127         [bezierPath lineToPoint: NSMakePoint((NSMinX(frame) + NSWidth(frame) - 1), NSMinY(frame) - 2.0)];
128         [bezierPath setLineWidth: 1.5];
129
130         if([self isEnabled]) {
131             [_strokeColor setStroke];
132         } else {
133             [_disabledStrokeColor setStroke];
134         }
135         [bezierPath stroke];
136     }
137 }
138
139 - (NSRect)drawTitle:(NSAttributedString *)title withFrame:(NSRect)frame inView:(NSView *)controlView
140 {
141     NSMutableAttributedString *newTitle = [title mutableCopy];
142
143     if([self isEnabled]) {
144         [newTitle addAttribute:NSForegroundColorAttributeName
145                          value:_cellTextColor
146                          range:NSMakeRange(0, [newTitle length])];
147     } else {
148         [newTitle addAttribute:NSForegroundColorAttributeName
149                          value:_disabledCellTextColor
150                          range:NSMakeRange(0, [newTitle length])];
151     }
152
153     return [super drawTitle: newTitle withFrame: frame inView: controlView];
154 }
155
156 @end