macOS: No custom HUD drawing on macOS 10.10+
[vlc.git] / modules / gui / macosx / VLCHUDStepperCell.m
1 //
2 //  BGHUDStepperCell.m
3 //  BGHUDAppKit
4 //
5 //  Created by BinaryGod on 4/6/09.
6 //
7 //  Copyright 2009 Tyler Bunnell and Steve Audette
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 "VLCHUDStepperCell.h"
36 #import "CompatibilityFixes.h"
37
38 @implementation VLCHUDStepperCell {
39     int topButtonFlag;
40     int bottomButtonFlag;
41
42     BOOL topPressed;
43     BOOL bottomPressed;
44     BOOL isTopDown;
45     BOOL isBottomDown;
46 }
47
48 - (instancetype)initWithCoder:(NSCoder *)coder
49 {
50     self = [super initWithCoder:coder];
51     if (self) {
52         _dropShadow = [[NSShadow alloc] init];
53         [_dropShadow setShadowColor: [NSColor blackColor]];
54         [_dropShadow setShadowBlurRadius: 2];
55         [_dropShadow setShadowOffset: NSMakeSize( 0, -1)];
56
57         _strokeColor = [NSColor colorWithDeviceRed: 0.749f green: 0.761f blue: 0.788f alpha: 1.0f];
58         _disabledStrokeColor = [NSColor colorWithDeviceRed: 0.749f green: 0.761f blue: 0.788f alpha:0.2f];
59
60         _normalGradient    = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceRed:0.251f green:0.251f blue:0.255f alpha:1.0f]
61                                                            endingColor:[NSColor colorWithDeviceRed:0.118f green:0.118f blue:0.118f alpha:1.0f]];
62         _disabledNormalComplexGradient = [[NSGradient alloc] initWithColorsAndLocations: [NSColor colorWithDeviceRed: 0.324f green: 0.331f blue: 0.347f alpha:0.5f],
63                                            (CGFloat)0, [NSColor colorWithDeviceRed: 0.245f green: 0.253f blue: 0.269f alpha: 0.5f], (CGFloat).5,
64                                            [NSColor colorWithDeviceRed: 0.206f green: 0.214f blue: 0.233f alpha: 0.5f], (CGFloat).5,
65                                            [NSColor colorWithDeviceRed: 0.139f green: 0.147f blue: 0.167f alpha: 0.5f], (CGFloat)1.0f, nil];
66         _pushedSolidFill = [NSColor colorWithDeviceRed: 0.941f green: 0.941f blue: 0.941f alpha: 0.5f];
67         _darkStrokeColor = [NSColor colorWithDeviceRed: 0.141f green: 0.141f blue: 0.141f alpha: 0.5f];
68     }
69     return self;
70 }
71
72 -(void)drawWithFrame:(NSRect) frame inView:(NSView *) controlView {
73     if (OSX_YOSEMITE_AND_HIGHER) {
74         return [super drawWithFrame:frame inView:controlView];
75     }
76     [self drawRoundRectButtonInFrame:frame];
77     [self drawArrowsInRect:frame];
78 }
79
80 -(NSRect)adjustFrame:(NSRect)frame
81 {
82     frame.origin.x += 3.5f;
83     frame.origin.y += 2.0f;
84     frame.size.width -= 7.0f;
85     frame.size.height -= 4.0f;
86     return frame;
87 }
88
89 -(BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView
90 {
91     if (OSX_YOSEMITE_AND_HIGHER) {
92         return [super startTrackingAt:startPoint inView:controlView];
93     }
94     NSRect frame = [controlView bounds];
95
96     NSRect bottomRect = NSMakeRect(frame.origin.x,frame.origin.y,frame.size.width,frame.size.height/2);
97     NSRect topRect = NSMakeRect(frame.origin.x,frame.origin.y+(frame.size.height/2),frame.size.width,frame.size.height/2);
98
99     if(NSPointInRect(startPoint,topRect))
100     {
101         topPressed = isTopDown = YES;
102     }
103     if(NSPointInRect(startPoint,bottomRect))
104     {
105         bottomPressed = isBottomDown = YES;
106     }
107     [[self controlView] setNeedsDisplay:YES];
108
109     return [super startTrackingAt:startPoint inView:controlView];
110 }
111 -(BOOL)continueTracking:(NSPoint)lastPoint at:(NSPoint)currentPoint inView:(NSView *)controlView
112 {
113     if (OSX_YOSEMITE_AND_HIGHER) {
114         return [super continueTracking:lastPoint at:currentPoint inView:controlView];
115     }
116     NSRect frame = [controlView bounds];
117
118     NSRect bottomRect = NSMakeRect(frame.origin.x,frame.origin.y,frame.size.width,frame.size.height/2);
119     NSRect topRect = NSMakeRect(frame.origin.x,frame.origin.y+(frame.size.height/2),frame.size.width,frame.size.height/2);
120
121     if(isTopDown && topPressed && !NSPointInRect(currentPoint,topRect))
122     {
123         isTopDown = NO;
124         [[self controlView] setNeedsDisplay:YES];
125     }
126     if(!isTopDown && topPressed && NSPointInRect(currentPoint,topRect))
127     {
128         isTopDown = YES;
129         [[self controlView] setNeedsDisplay:YES];
130     }
131     if(isBottomDown && bottomPressed && !NSPointInRect(currentPoint,bottomRect))
132     {
133         isBottomDown = NO;
134         [[self controlView] setNeedsDisplay:YES];
135     }
136     if(!isBottomDown && bottomPressed && NSPointInRect(currentPoint,bottomRect))
137     {
138         isBottomDown = YES;
139         [[self controlView] setNeedsDisplay:YES];
140     }
141
142     return [super continueTracking:lastPoint at:currentPoint inView:controlView];
143 }
144 -(void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint inView:(NSView *)controlView mouseIsUp:(BOOL)flag
145 {
146     if (OSX_YOSEMITE_AND_HIGHER) {
147         return [super stopTracking:lastPoint at:stopPoint inView:controlView mouseIsUp:flag];
148     }
149     isTopDown = isBottomDown = topPressed = bottomPressed = NO;
150     [[self controlView] setNeedsDisplay:YES];
151     [super stopTracking:lastPoint at:stopPoint inView:controlView mouseIsUp:flag];
152 }
153
154 -(void)drawRoundRectButtonInFrame:(NSRect)frame {
155
156     frame = [self adjustFrame:frame];
157
158     float cornerRadius = 4.0f;
159
160     //Draw the complete button
161
162     //Create Path
163     NSBezierPath *path = [[NSBezierPath alloc] init];
164
165     //Bottom Right Corner
166     [path moveToPoint:NSMakePoint(NSMaxX(frame), NSMinY(frame) + cornerRadius)];
167
168     //Right Edge
169     [path lineToPoint:NSMakePoint(NSMaxX(frame), NSMaxY(frame) - cornerRadius)];
170
171     //Top Right Curve
172     [path appendBezierPathWithArcWithCenter: NSMakePoint(NSMaxX(frame) - cornerRadius, NSMaxY(frame) - cornerRadius)
173                                      radius: cornerRadius
174                                  startAngle: 0
175                                    endAngle: 90];
176
177     //Top Edge
178     [path lineToPoint:NSMakePoint(NSMinX(frame) + cornerRadius, NSMaxY(frame))];
179
180     //Top Left Curve
181     [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(frame) + cornerRadius, NSMaxY(frame) - cornerRadius)
182                                      radius: cornerRadius
183                                  startAngle: 90
184                                    endAngle: 180];
185
186     //Left Edge
187     [path lineToPoint:NSMakePoint(NSMinX(frame), NSMinY(frame) + cornerRadius)];
188
189     //Left Bottom Curve
190     [path appendBezierPathWithArcWithCenter: NSMakePoint(NSMinX(frame) + cornerRadius, NSMinY(frame) + cornerRadius)
191                                      radius: cornerRadius
192                                  startAngle: 180
193                                    endAngle: 270];
194
195     //Bottom Edge
196     [path lineToPoint:NSMakePoint(NSMaxX(frame) - cornerRadius, NSMinY(frame))];
197
198     //Right Bottom Curve
199     [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(frame) - cornerRadius, NSMinY(frame) + cornerRadius)
200                                      radius: cornerRadius
201                                  startAngle: 270
202                                    endAngle: 0];
203
204     [path closePath];
205
206
207     if([self isEnabled]) {
208
209         [_normalGradient drawInBezierPath:path relativeCenterPosition:NSZeroPoint];
210
211     } else {
212
213         [_disabledNormalComplexGradient drawInBezierPath:path relativeCenterPosition:NSZeroPoint];
214     }
215
216
217
218     //Check for anything being pushed
219     if([self isEnabled])
220     {
221         if(isTopDown)
222         {
223             NSRect topRect = NSMakeRect(frame.origin.x,frame.origin.y+(frame.size.height/2),frame.size.width,frame.size.height/2);
224             NSBezierPath *path = [[NSBezierPath alloc] init];
225             [path moveToPoint:NSMakePoint(NSMaxX(topRect), NSMinY(topRect))];
226             [path lineToPoint:NSMakePoint(NSMaxX(topRect), NSMaxY(topRect) - cornerRadius)];
227             [path appendBezierPathWithArcWithCenter: NSMakePoint(NSMaxX(topRect) - cornerRadius, NSMaxY(topRect) - cornerRadius)
228                                              radius: cornerRadius
229                                          startAngle: 0
230                                            endAngle: 90];
231             [path lineToPoint:NSMakePoint(NSMinX(topRect) + cornerRadius, NSMaxY(topRect))];
232             [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(topRect) + cornerRadius, NSMaxY(topRect) - cornerRadius)
233                                              radius: cornerRadius
234                                          startAngle: 90
235                                            endAngle: 180];
236             [path lineToPoint:NSMakePoint(NSMinX(topRect), NSMinY(topRect))];
237
238             [path closePath];
239
240             [_pushedSolidFill set];
241             [path fill];
242         }
243         else if(isBottomDown)
244         {
245             NSRect bottomRect = NSMakeRect(frame.origin.x,frame.origin.y,frame.size.width,frame.size.height/2);
246             NSBezierPath* path = [[NSBezierPath alloc] init];
247
248             [path moveToPoint:NSMakePoint(NSMinX(bottomRect), NSMaxY(bottomRect))];
249             [path lineToPoint:NSMakePoint(NSMinX(bottomRect), NSMinY(bottomRect) + cornerRadius)];
250             [path appendBezierPathWithArcWithCenter: NSMakePoint(NSMinX(bottomRect) + cornerRadius, NSMinY(bottomRect) + cornerRadius)
251                                              radius: cornerRadius
252                                          startAngle: 180
253                                            endAngle: 270];
254             [path lineToPoint:NSMakePoint(NSMaxX(bottomRect) - cornerRadius, NSMinY(bottomRect))];
255             [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(bottomRect) - cornerRadius, NSMinY(bottomRect) + cornerRadius)
256                                              radius: cornerRadius
257                                          startAngle: 270
258                                            endAngle: 0];
259             [path lineToPoint:NSMakePoint(NSMaxX(bottomRect), NSMaxY(bottomRect))];
260
261             [path closePath];
262             [_pushedSolidFill set];
263             [path fill];
264         }
265     }
266
267     [NSGraphicsContext saveGraphicsState];
268
269     //Draw dark border color
270     if([self isEnabled]) {
271
272         [_dropShadow set];
273     }
274     [_darkStrokeColor set];
275     [path stroke];
276
277     [NSGraphicsContext restoreGraphicsState];
278
279     if([self isEnabled]) {
280
281         [_strokeColor set];
282     } else {
283
284         [_disabledStrokeColor set];
285     }
286
287     [path setLineWidth: 1.0f];
288     [path stroke];
289
290
291 }
292
293 -(void)drawArrowsInRect:(NSRect) frame {
294
295     CGFloat arrowWidth = 2.5f;
296     CGFloat arrowHeight = 2.0f;
297
298     frame = [self adjustFrame:frame];
299
300     NSRect bottomRect = NSMakeRect(frame.origin.x,frame.origin.y,frame.size.width,frame.size.height/2);
301     NSRect topRect = NSMakeRect(frame.origin.x,frame.origin.y+(frame.size.height/2),frame.size.width,frame.size.height/2);
302
303     NSBezierPath *arrow = [[NSBezierPath alloc] init];
304
305     NSPoint points[3];
306
307     points[0] = NSMakePoint(topRect.origin.x + (topRect.size.width /2), topRect.origin.y + ((topRect.size.height /2) + arrowHeight));
308     points[1] = NSMakePoint(topRect.origin.x + ((topRect.size.width /2) - arrowWidth), topRect.origin.y + ((topRect.size.height /2)-arrowHeight));
309     points[2] = NSMakePoint(topRect.origin.x + ((topRect.size.width /2) + arrowWidth), topRect.origin.y + ((topRect.size.height /2)-arrowHeight));
310     
311     
312     [arrow appendBezierPathWithPoints: points count: 3];
313     
314     if([self isEnabled]) {
315         if(isTopDown)
316             [_darkStrokeColor set];
317         else
318             [_strokeColor set];
319     } else {
320         [_disabledStrokeColor set];
321     }
322     
323     
324     [arrow fill];
325     
326     
327     arrow = [[NSBezierPath alloc] init];
328     
329     points[0] = NSMakePoint(bottomRect.origin.x + ((bottomRect.size.width /2) - arrowWidth), bottomRect.origin.y + ((bottomRect.size.height /2)+arrowHeight));
330     points[1] = NSMakePoint(bottomRect.origin.x + ((bottomRect.size.width /2) + arrowWidth), bottomRect.origin.y + ((bottomRect.size.height /2)+arrowHeight));
331     points[2] = NSMakePoint(bottomRect.origin.x + (bottomRect.size.width /2), frame.origin.y + ((bottomRect.size.height /2) - arrowHeight));
332     
333     [arrow appendBezierPathWithPoints: points count: 3];
334     
335     if([self isEnabled]) {
336         if(isBottomDown)
337             [_darkStrokeColor set];
338         else
339             [_strokeColor set];
340     } else {
341         [_disabledStrokeColor set];
342     }
343     
344     [arrow fill];
345 }
346
347 @end