1 /*****************************************************************************
2 * VLCHUDSliderCell.m: Custom slider cell UI for dark HUD Panels
3 *****************************************************************************
4 * Copyright (C) 2016 VLC authors and VideoLAN
7 * Authors: Marvin Scholz <epirat07 -at- gmail -dot- com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 #import "VLCHUDSliderCell.h"
26 @implementation VLCHUDSliderCell
28 - (instancetype)initWithCoder:(NSCoder *)coder
30 self = [super initWithCoder:coder];
32 // Custom colors for the slider
33 _sliderColor = [NSColor colorWithCalibratedRed:0.318 green:0.318 blue:0.318 alpha:0.6];
34 _disabledSliderColor = [NSColor colorWithCalibratedRed:0.318 green:0.318 blue:0.318 alpha:0.2];
35 _strokeColor = [NSColor colorWithCalibratedRed:0.749 green:0.761 blue:0.788 alpha:1.0];
36 _disabledStrokeColor = [NSColor colorWithCalibratedRed:0.749 green:0.761 blue:0.788 alpha:0.2];
39 // Custom knob gradients
40 _knobGradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceRed:0.251 green:0.251 blue:0.255 alpha:1.0]
41 endingColor:[NSColor colorWithDeviceRed:0.118 green:0.118 blue:0.118 alpha:1.0]];
42 _disableKnobGradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceRed:0.251 green:0.251 blue:0.255 alpha:1.0]
43 endingColor:[NSColor colorWithDeviceRed:0.118 green:0.118 blue:0.118 alpha:1.0]];
48 NSAffineTransform* RotationTransform(const CGFloat angle, const NSPoint point)
50 NSAffineTransform* transform = [NSAffineTransform transform];
51 [transform translateXBy:point.x yBy:point.y];
52 [transform rotateByRadians:angle];
53 [transform translateXBy:-(point.x) yBy:-(point.y)];
57 - (void) drawKnob:(NSRect)smallRect
59 NSBezierPath *path = [NSBezierPath bezierPath];
60 // Inset rect to have enough room for the stroke
61 smallRect = NSInsetRect(smallRect, 0.5, 0.5);
63 // Get min/max/mid coords for shape calculations
64 CGFloat minX = NSMinX(smallRect);
65 CGFloat minY = NSMinY(smallRect);
66 CGFloat maxX = NSMaxX(smallRect);
67 CGFloat maxY = NSMaxY(smallRect);
68 CGFloat midX = NSMidX(smallRect);
69 CGFloat midY = NSMidY(smallRect);
71 // Draw the knobs shape
72 if (self.numberOfTickMarks > 0) {
73 // We have tickmarks, draw an arrow-like shape
74 if (self.isVertical) {
75 // For some reason the rect is not alligned correctly at
76 // tickmarks and clipped, so this ugly thing is necessary:
80 // Right pointing arrow
81 [path moveToPoint:NSMakePoint(minX + 3, minY)];
82 [path lineToPoint:NSMakePoint(midX + 2, minY)];
83 [path lineToPoint:NSMakePoint(maxX, midY)];
84 [path lineToPoint:NSMakePoint(midX + 2, maxY)];
85 [path lineToPoint:NSMakePoint(minX + 3, maxY)];
86 [path appendBezierPathWithArcFromPoint:NSMakePoint(minX, maxY)
87 toPoint:NSMakePoint(minX, maxY - 3)
89 [path lineToPoint:NSMakePoint(minX, maxY - 3)];
90 [path lineToPoint:NSMakePoint(minX, minY + 3)];
91 [path appendBezierPathWithArcFromPoint:NSMakePoint(minX, minY)
92 toPoint:NSMakePoint(minX + 3, minY)
96 // Down pointing arrow
97 [path moveToPoint:NSMakePoint(minX + 3, minY)];
98 [path lineToPoint:NSMakePoint(maxX - 3, minY)];
99 [path appendBezierPathWithArcFromPoint:NSMakePoint(maxX, minY)
100 toPoint:NSMakePoint(maxX, minY + 3)
102 [path lineToPoint:NSMakePoint(maxX, minY + 3)];
103 [path lineToPoint:NSMakePoint(maxX, midY + 2)];
104 [path lineToPoint:NSMakePoint(midX, maxY)];
105 [path lineToPoint:NSMakePoint(minX, midY + 2)];
106 [path lineToPoint:NSMakePoint(minX, minY + 3)];
107 [path appendBezierPathWithArcFromPoint:NSMakePoint(minX, minY)
108 toPoint:NSMakePoint(minX + 3, minY)
113 // Rotate our knob if needed to the correct position
114 if (self.tickMarkPosition == NSTickMarkAbove) {
115 NSAffineTransform *transform = nil;
116 transform = RotationTransform(M_PI, NSMakePoint(midX, midY));
117 [path transformUsingAffineTransform:transform];
120 // We have no tickmarks, draw a round knob
121 [path appendBezierPathWithOvalInRect:NSInsetRect(smallRect, 0.5, 0.5)];
124 // Draw the knobs background
125 if (self.isEnabled && self.isHighlighted) {
126 [_knobGradient drawInBezierPath:path angle:270.0f];
127 } else if (self.isEnabled) {
128 [_knobGradient drawInBezierPath:path angle:90.0f];
130 [_disableKnobGradient drawInBezierPath:path angle:90.0f];
133 // Draw white stroke around the knob
134 if (self.isEnabled) {
135 [_strokeColor setStroke];
137 [_disabledStrokeColor setStroke];
140 [path setLineWidth:1.0];
144 - (void)drawBarInside:(NSRect)fullRect flipped:(BOOL)flipped
148 // Determine current position of knob
149 CGFloat knobPosition = (self.doubleValue - self.minValue) / (self.maxValue - self.minValue);
152 NSRect activeRect = fullRect;
154 if (self.isVertical) {
155 // Calculate active rect (bottom part of slider)
157 activeRect.origin.y = (1 - knobPosition) * activeRect.size.height;
158 activeRect.size.height -= activeRect.origin.y - 1;
160 activeRect.size.height -= (1 - knobPosition) * activeRect.size.height - 1;
163 // Calculate active rect (left part of slider)
164 activeRect.size.width = knobPosition * (self.controlView.frame.size.width - 1.0);
168 [_disabledSliderColor setFill];
169 path = [NSBezierPath bezierPathWithRoundedRect:fullRect xRadius:2.0 yRadius:2.0];
173 [_sliderColor setFill];
174 path = [NSBezierPath bezierPathWithRoundedRect:activeRect xRadius:2.0 yRadius:2.0];
178 - (void)drawTickMarks
180 for (int i = 0; i < self.numberOfTickMarks; i++) {
181 NSRect tickMarkRect = [self rectOfTickMarkAtIndex:i];
182 if (self.isEnabled) {
183 [_strokeColor setFill];
185 [_disabledStrokeColor setFill];
187 NSRectFill(tickMarkRect);