You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

343 lines
12 KiB

//
// VLCHUDSliderCell.m
// BGHUDAppKit
//
// Created by BinaryGod on 5/30/08.
//
// Copyright (c) 2008, Tim Davis (BinaryMethod.com, binary.god@gmail.com)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
// Neither the name of the BinaryMethod.com nor the names of its contributors
// may be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#import "VLCHUDSliderCell.h"
#import "CompatibilityFixes.h"
#import "NSGradient+VLCAdditions.h"
@implementation VLCHUDSliderCell
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
// Custom colors for the slider
_sliderColor = [NSColor colorWithCalibratedRed:0.318 green:0.318 blue:0.318 alpha:0.6];
_disabledSliderColor = [NSColor colorWithCalibratedRed:0.318 green:0.318 blue:0.318 alpha:0.2];
_strokeColor = [NSColor colorWithCalibratedRed:0.749 green:0.761 blue:0.788 alpha:1.0];
_disabledStrokeColor = [NSColor colorWithCalibratedRed:0.749 green:0.761 blue:0.788 alpha:0.2];
// Custom knob gradients
_knobGradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceRed:0.251 green:0.251 blue:0.255 alpha:1.0]
endingColor:[NSColor colorWithDeviceRed:0.118 green:0.118 blue:0.118 alpha:1.0]];
_disableKnobGradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceRed:0.251 green:0.251 blue:0.255 alpha:1.0]
endingColor:[NSColor colorWithDeviceRed:0.118 green:0.118 blue:0.118 alpha:1.0]];
}
return self;
}
NSAffineTransform* RotationTransform(const CGFloat angle, const NSPoint point)
{
NSAffineTransform* transform = [NSAffineTransform transform];
[transform translateXBy:point.x yBy:point.y];
[transform rotateByRadians:angle];
[transform translateXBy:-(point.x) yBy:-(point.y)];
return transform;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpartial-availability"
- (void)drawKnob:(NSRect)smallRect
{
if (OSX_YOSEMITE_AND_HIGHER) {
return [super drawKnob:smallRect];
}
NSBezierPath *path = [NSBezierPath bezierPath];
// Inset rect to have enough room for the stroke
smallRect = NSInsetRect(smallRect, 1.0, 1.0);
// Get min/max/mid coords for shape calculations
CGFloat minX = NSMinX(smallRect);
CGFloat minY = NSMinY(smallRect);
CGFloat maxX = NSMaxX(smallRect);
CGFloat maxY = NSMaxY(smallRect);
CGFloat midX = NSMidX(smallRect);
CGFloat midY = NSMidY(smallRect);
// Draw the knobs shape
if (self.numberOfTickMarks > 0) {
// We have tickmarks, draw an arrow-like shape
if (self.isVertical) {
// For some reason the rect is not alligned correctly at
// tickmarks and clipped, so this ugly thing is necessary:
maxY = maxY - 2;
midY = midY - 1;
// Right pointing arrow
[path moveToPoint:NSMakePoint(minX + 3, minY)];
[path lineToPoint:NSMakePoint(midX + 2, minY)];
[path lineToPoint:NSMakePoint(maxX, midY)];
[path lineToPoint:NSMakePoint(midX + 2, maxY)];
[path lineToPoint:NSMakePoint(minX + 3, maxY)];
[path appendBezierPathWithArcFromPoint:NSMakePoint(minX, maxY)
toPoint:NSMakePoint(minX, maxY - 3)
radius:2.5f];
[path lineToPoint:NSMakePoint(minX, maxY - 3)];
[path lineToPoint:NSMakePoint(minX, minY + 3)];
[path appendBezierPathWithArcFromPoint:NSMakePoint(minX, minY)
toPoint:NSMakePoint(minX + 3, minY)
radius:2.5f];
[path closePath];
} else {
// Down pointing arrow
[path moveToPoint:NSMakePoint(minX + 3, minY)];
[path lineToPoint:NSMakePoint(maxX - 3, minY)];
[path appendBezierPathWithArcFromPoint:NSMakePoint(maxX, minY)
toPoint:NSMakePoint(maxX, minY + 3)
radius:2.5f];
[path lineToPoint:NSMakePoint(maxX, minY + 3)];
[path lineToPoint:NSMakePoint(maxX, midY + 2)];
[path lineToPoint:NSMakePoint(midX, maxY)];
[path lineToPoint:NSMakePoint(minX, midY + 2)];
[path lineToPoint:NSMakePoint(minX, minY + 3)];
[path appendBezierPathWithArcFromPoint:NSMakePoint(minX, minY)
toPoint:NSMakePoint(minX + 3, minY)
radius:2.5f];
[path closePath];
}
// Rotate our knob if needed to the correct position
if (self.tickMarkPosition == NSTickMarkAbove) {
NSAffineTransform *transform = nil;
transform = RotationTransform(M_PI, NSMakePoint(midX, midY));
[path transformUsingAffineTransform:transform];
}
} else {
// We have no tickmarks, draw a round knob
[path appendBezierPathWithOvalInRect:NSInsetRect(smallRect, 0.5, 0.5)];
}
// Draw the knobs background
if (self.isEnabled && self.isHighlighted) {
[_knobGradient vlc_safeDrawInBezierPath:path angle:270.0f];
} else if (self.isEnabled) {
[_knobGradient vlc_safeDrawInBezierPath:path angle:90.0f];
} else {
[_disableKnobGradient vlc_safeDrawInBezierPath:path angle:90.0f];
}
// Draw white stroke around the knob
if (self.isEnabled) {
[_strokeColor setStroke];
} else {
[_disabledStrokeColor setStroke];
}
[path setLineWidth:1.0];
[path stroke];
}
- (void)drawBarInside:(NSRect)fullRect flipped:(BOOL)flipped
{
if (OSX_YOSEMITE_AND_HIGHER) {
return [super drawBarInside:fullRect flipped:flipped];
}
if (self.isVertical) {
return [self drawVerticalBarInFrame:fullRect];
} else {
return [self drawHorizontalBarInFrame:fullRect];
}
}
#pragma clang diagnostic pop
- (void)drawVerticalBarInFrame:(NSRect)frame
{
// Adjust frame based on ControlSize
switch ([self controlSize]) {
case NSRegularControlSize:
if ([self numberOfTickMarks] != 0) {
if ([self tickMarkPosition] == NSTickMarkRight) {
frame.origin.x += 4;
} else {
frame.origin.x += frame.size.width - 9;
}
} else {
frame.origin.x = frame.origin.x + (((frame.origin.x + frame.size.width) /2) - 2.5f);
}
frame.origin.x += 0.5f;
frame.origin.y += 2.5f;
frame.size.height -= 6;
frame.size.width = 5;
break;
case NSSmallControlSize:
if ([self numberOfTickMarks] != 0) {
if ([self tickMarkPosition] == NSTickMarkRight) {
frame.origin.x += 3;
} else {
frame.origin.x += frame.size.width - 8;
}
} else {
frame.origin.x = frame.origin.x + (((frame.origin.x + frame.size.width) /2) - 2.5f);
}
frame.origin.y += 0.5f;
frame.size.height -= 1;
frame.origin.x += 0.5f;
frame.size.width = 5;
break;
case NSMiniControlSize:
if ([self numberOfTickMarks] != 0) {
if ([self tickMarkPosition] == NSTickMarkRight) {
frame.origin.x += 2.5f;
} else {
frame.origin.x += frame.size.width - 6.5f;
}
} else {
frame.origin.x = frame.origin.x + (((frame.origin.x + frame.size.width) /2) - 2);
}
frame.origin.x += 1;
frame.origin.y += 0.5f;
frame.size.height -= 1;
frame.size.width = 3;
break;
}
// Draw Bar
NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect: frame xRadius: 2 yRadius: 2];
if ([self isEnabled]) {
[_sliderColor set];
[path fill];
[_strokeColor set];
[path stroke];
} else {
[_disabledSliderColor set];
[path fill];
[_disabledStrokeColor set];
[path stroke];
}
}
- (void)drawHorizontalBarInFrame:(NSRect)frame
{
// Adjust frame based on ControlSize
switch ([self controlSize]) {
case NSRegularControlSize:
if ([self numberOfTickMarks] != 0) {
if ([self tickMarkPosition] == NSTickMarkBelow) {
frame.origin.y += 4;
} else {
frame.origin.y += frame.size.height - 10;
}
} else {
frame.origin.y = frame.origin.y + (((frame.origin.y + frame.size.height) /2) - 2.5f);
}
frame.origin.x += 2.5f;
frame.origin.y += 0.5f;
frame.size.width -= 5;
frame.size.height = 5;
break;
case NSSmallControlSize:
if ([self numberOfTickMarks] != 0) {
if ([self tickMarkPosition] == NSTickMarkBelow) {
frame.origin.y += 2;
} else {
frame.origin.y += frame.size.height - 8;
}
} else {
frame.origin.y = frame.origin.y + (((frame.origin.y + frame.size.height) /2) - 2.5f);
}
frame.origin.x += 0.5f;
frame.origin.y += 0.5f;
frame.size.width -= 1;
frame.size.height = 5;
break;
case NSMiniControlSize:
if ([self numberOfTickMarks] != 0) {
if ([self tickMarkPosition] == NSTickMarkBelow) {
frame.origin.y += 2;
} else {
frame.origin.y += frame.size.height - 6;
}
} else {
frame.origin.y = frame.origin.y + (((frame.origin.y + frame.size.height) /2) - 2);
}
frame.origin.x += 0.5f;
frame.origin.y += 0.5f;
frame.size.width -= 1;
frame.size.height = 3;
break;
}
// Draw Bar
NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:frame xRadius:2 yRadius:2];
if ([self isEnabled]) {
[_sliderColor set];
[path fill];
[_strokeColor set];
[path stroke];
} else {
[_disabledSliderColor set];
[path fill];
[_disabledStrokeColor set];
[path stroke];
}
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpartial-availability"
- (void)drawTickMarks
{
if (OSX_YOSEMITE_AND_HIGHER) {
return [super drawTickMarks];
}
for (int i = 0; i < self.numberOfTickMarks; i++) {
NSRect tickMarkRect = [self rectOfTickMarkAtIndex:i];
if (self.isEnabled) {
[_strokeColor setFill];
} else {
[_disabledStrokeColor setFill];
}
NSRectFill(tickMarkRect);
}
}
#pragma clang diagnostic pop
@end