5 // Created by BinaryGod on 5/30/08.
7 // Copyright (c) 2008, Tim Davis (BinaryMethod.com, binary.god@gmail.com)
8 // All rights reserved.
10 // Redistribution and use in source and binary forms, with or without modification,
11 // are permitted provided that the following conditions are met:
13 // Redistributions of source code must retain the above copyright notice, this
14 // list of conditions and the following disclaimer.
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.
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.
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.
35 #import "VLCHUDSliderCell.h"
37 @implementation VLCHUDSliderCell
39 - (instancetype)initWithCoder:(NSCoder *)coder
41 self = [super initWithCoder:coder];
43 // Custom colors for the slider
44 _sliderColor = [NSColor colorWithCalibratedRed:0.318 green:0.318 blue:0.318 alpha:0.6];
45 _disabledSliderColor = [NSColor colorWithCalibratedRed:0.318 green:0.318 blue:0.318 alpha:0.2];
46 _strokeColor = [NSColor colorWithCalibratedRed:0.749 green:0.761 blue:0.788 alpha:1.0];
47 _disabledStrokeColor = [NSColor colorWithCalibratedRed:0.749 green:0.761 blue:0.788 alpha:0.2];
49 // Custom knob gradients
50 _knobGradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceRed:0.251 green:0.251 blue:0.255 alpha:1.0]
51 endingColor:[NSColor colorWithDeviceRed:0.118 green:0.118 blue:0.118 alpha:1.0]];
52 _disableKnobGradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceRed:0.251 green:0.251 blue:0.255 alpha:1.0]
53 endingColor:[NSColor colorWithDeviceRed:0.118 green:0.118 blue:0.118 alpha:1.0]];
58 NSAffineTransform* RotationTransform(const CGFloat angle, const NSPoint point)
60 NSAffineTransform* transform = [NSAffineTransform transform];
61 [transform translateXBy:point.x yBy:point.y];
62 [transform rotateByRadians:angle];
63 [transform translateXBy:-(point.x) yBy:-(point.y)];
67 #pragma clang diagnostic push
68 #pragma clang diagnostic ignored "-Wpartial-availability"
69 - (void)drawKnob:(NSRect)smallRect
71 NSBezierPath *path = [NSBezierPath bezierPath];
72 // Inset rect to have enough room for the stroke
73 smallRect = NSInsetRect(smallRect, 1.0, 1.0);
75 // Get min/max/mid coords for shape calculations
76 CGFloat minX = NSMinX(smallRect);
77 CGFloat minY = NSMinY(smallRect);
78 CGFloat maxX = NSMaxX(smallRect);
79 CGFloat maxY = NSMaxY(smallRect);
80 CGFloat midX = NSMidX(smallRect);
81 CGFloat midY = NSMidY(smallRect);
83 // Draw the knobs shape
84 if (self.numberOfTickMarks > 0) {
85 // We have tickmarks, draw an arrow-like shape
86 if (self.isVertical) {
87 // For some reason the rect is not alligned correctly at
88 // tickmarks and clipped, so this ugly thing is necessary:
92 // Right pointing arrow
93 [path moveToPoint:NSMakePoint(minX + 3, minY)];
94 [path lineToPoint:NSMakePoint(midX + 2, minY)];
95 [path lineToPoint:NSMakePoint(maxX, midY)];
96 [path lineToPoint:NSMakePoint(midX + 2, maxY)];
97 [path lineToPoint:NSMakePoint(minX + 3, maxY)];
98 [path appendBezierPathWithArcFromPoint:NSMakePoint(minX, maxY)
99 toPoint:NSMakePoint(minX, maxY - 3)
101 [path lineToPoint:NSMakePoint(minX, maxY - 3)];
102 [path lineToPoint:NSMakePoint(minX, minY + 3)];
103 [path appendBezierPathWithArcFromPoint:NSMakePoint(minX, minY)
104 toPoint:NSMakePoint(minX + 3, minY)
108 // Down pointing arrow
109 [path moveToPoint:NSMakePoint(minX + 3, minY)];
110 [path lineToPoint:NSMakePoint(maxX - 3, minY)];
111 [path appendBezierPathWithArcFromPoint:NSMakePoint(maxX, minY)
112 toPoint:NSMakePoint(maxX, minY + 3)
114 [path lineToPoint:NSMakePoint(maxX, minY + 3)];
115 [path lineToPoint:NSMakePoint(maxX, midY + 2)];
116 [path lineToPoint:NSMakePoint(midX, maxY)];
117 [path lineToPoint:NSMakePoint(minX, midY + 2)];
118 [path lineToPoint:NSMakePoint(minX, minY + 3)];
119 [path appendBezierPathWithArcFromPoint:NSMakePoint(minX, minY)
120 toPoint:NSMakePoint(minX + 3, minY)
125 // Rotate our knob if needed to the correct position
126 if (self.tickMarkPosition == NSTickMarkAbove) {
127 NSAffineTransform *transform = nil;
128 transform = RotationTransform(M_PI, NSMakePoint(midX, midY));
129 [path transformUsingAffineTransform:transform];
132 // We have no tickmarks, draw a round knob
133 [path appendBezierPathWithOvalInRect:NSInsetRect(smallRect, 0.5, 0.5)];
136 // Draw the knobs background
137 if (self.isEnabled && self.isHighlighted) {
138 [_knobGradient drawInBezierPath:path angle:270.0f];
139 } else if (self.isEnabled) {
140 [_knobGradient drawInBezierPath:path angle:90.0f];
142 [_disableKnobGradient drawInBezierPath:path angle:90.0f];
145 // Draw white stroke around the knob
146 if (self.isEnabled) {
147 [_strokeColor setStroke];
149 [_disabledStrokeColor setStroke];
152 [path setLineWidth:1.0];
156 - (void)drawBarInside:(NSRect)fullRect flipped:(BOOL)flipped
158 if (self.isVertical) {
159 return [self drawVerticalBarInFrame:fullRect];
161 return [self drawHorizontalBarInFrame:fullRect];
164 #pragma clang diagnostic pop
166 - (void)drawVerticalBarInFrame:(NSRect)frame
168 // Adjust frame based on ControlSize
169 switch ([self controlSize]) {
171 case NSRegularControlSize:
173 if ([self numberOfTickMarks] != 0) {
174 if ([self tickMarkPosition] == NSTickMarkRight) {
177 frame.origin.x += frame.size.width - 9;
180 frame.origin.x = frame.origin.x + (((frame.origin.x + frame.size.width) /2) - 2.5f);
182 frame.origin.x += 0.5f;
183 frame.origin.y += 2.5f;
184 frame.size.height -= 6;
185 frame.size.width = 5;
188 case NSSmallControlSize:
190 if ([self numberOfTickMarks] != 0) {
191 if ([self tickMarkPosition] == NSTickMarkRight) {
194 frame.origin.x += frame.size.width - 8;
197 frame.origin.x = frame.origin.x + (((frame.origin.x + frame.size.width) /2) - 2.5f);
199 frame.origin.y += 0.5f;
200 frame.size.height -= 1;
201 frame.origin.x += 0.5f;
202 frame.size.width = 5;
205 case NSMiniControlSize:
207 if ([self numberOfTickMarks] != 0) {
208 if ([self tickMarkPosition] == NSTickMarkRight) {
209 frame.origin.x += 2.5f;
211 frame.origin.x += frame.size.width - 6.5f;
214 frame.origin.x = frame.origin.x + (((frame.origin.x + frame.size.width) /2) - 2);
217 frame.origin.y += 0.5f;
218 frame.size.height -= 1;
219 frame.size.width = 3;
224 NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect: frame xRadius: 2 yRadius: 2];
226 if ([self isEnabled]) {
233 [_disabledSliderColor set];
236 [_disabledStrokeColor set];
241 - (void)drawHorizontalBarInFrame:(NSRect)frame
243 // Adjust frame based on ControlSize
244 switch ([self controlSize]) {
246 case NSRegularControlSize:
248 if ([self numberOfTickMarks] != 0) {
249 if ([self tickMarkPosition] == NSTickMarkBelow) {
252 frame.origin.y += frame.size.height - 10;
255 frame.origin.y = frame.origin.y + (((frame.origin.y + frame.size.height) /2) - 2.5f);
257 frame.origin.x += 2.5f;
258 frame.origin.y += 0.5f;
259 frame.size.width -= 5;
260 frame.size.height = 5;
263 case NSSmallControlSize:
265 if ([self numberOfTickMarks] != 0) {
266 if ([self tickMarkPosition] == NSTickMarkBelow) {
269 frame.origin.y += frame.size.height - 8;
272 frame.origin.y = frame.origin.y + (((frame.origin.y + frame.size.height) /2) - 2.5f);
274 frame.origin.x += 0.5f;
275 frame.origin.y += 0.5f;
276 frame.size.width -= 1;
277 frame.size.height = 5;
280 case NSMiniControlSize:
282 if ([self numberOfTickMarks] != 0) {
283 if ([self tickMarkPosition] == NSTickMarkBelow) {
286 frame.origin.y += frame.size.height - 6;
289 frame.origin.y = frame.origin.y + (((frame.origin.y + frame.size.height) /2) - 2);
291 frame.origin.x += 0.5f;
292 frame.origin.y += 0.5f;
293 frame.size.width -= 1;
294 frame.size.height = 3;
299 NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:frame xRadius:2 yRadius:2];
301 if ([self isEnabled]) {
308 [_disabledSliderColor set];
311 [_disabledStrokeColor set];
316 - (void)drawTickMarks
318 for (int i = 0; i < self.numberOfTickMarks; i++) {
319 NSRect tickMarkRect = [self rectOfTickMarkAtIndex:i];
320 if (self.isEnabled) {
321 [_strokeColor setFill];
323 [_disabledStrokeColor setFill];
325 NSRectFill(tickMarkRect);