Commit 105fa81d authored by Marvin Scholz's avatar Marvin Scholz

macosx: Add VLCSlider(Cell)

parent e14221d5
......@@ -70,6 +70,8 @@
1C31140D1E508C8800D4DD76 /* SPMediaKeyTap.m in Sources */ = {isa = PBXBuildFile; fileRef = CCF0777C13659A8000AF19FD /* SPMediaKeyTap.m */; };
1C69FDF61EAB30C7007724ED /* Windows.m in Sources */ = {isa = PBXBuildFile; fileRef = E06CF7F516020F6200C698B7 /* Windows.m */; };
1CFE8D591EA0D42A00E94451 /* VLCErrorWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CFE8D581EA0D42A00E94451 /* VLCErrorWindowController.m */; };
6B0AB0F01F1AC8B3003A1B4E /* VLCSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B0AB0ED1F1AC8B3003A1B4E /* VLCSlider.m */; };
6B0AB0F11F1AC8B3003A1B4E /* VLCSliderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B0AB0EF1F1AC8B3003A1B4E /* VLCSliderCell.m */; };
6B3BE42C1E6217CB008D098A /* VLCImageButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B3BE42B1E6217CB008D098A /* VLCImageButton.m */; };
6B4D50901E79781F004479B5 /* VLCHotkeyChangeWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B4D508F1E79781F004479B5 /* VLCHotkeyChangeWindow.m */; };
6B4D50931E7979CB004479B5 /* VLCSimplePrefsWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B4D50921E7979CB004479B5 /* VLCSimplePrefsWindow.m */; };
......@@ -122,6 +124,10 @@
5CCED71514C0D4A90057F8D1 /* VLCUIWidgets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCUIWidgets.m; sourceTree = "<group>"; };
633121CA1B51122700E636DA /* VLCResumeDialogController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCResumeDialogController.h; sourceTree = "<group>"; };
633121CB1B51122700E636DA /* VLCResumeDialogController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCResumeDialogController.m; sourceTree = "<group>"; };
6B0AB0EC1F1AC8B3003A1B4E /* VLCSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCSlider.h; sourceTree = "<group>"; };
6B0AB0ED1F1AC8B3003A1B4E /* VLCSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCSlider.m; sourceTree = "<group>"; };
6B0AB0EE1F1AC8B3003A1B4E /* VLCSliderCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCSliderCell.h; sourceTree = "<group>"; };
6B0AB0EF1F1AC8B3003A1B4E /* VLCSliderCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCSliderCell.m; sourceTree = "<group>"; };
6B13E2A61BC67678001AD24A /* VLCScrollingClipView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCScrollingClipView.h; sourceTree = "<group>"; };
6B13E2A71BC67678001AD24A /* VLCScrollingClipView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCScrollingClipView.m; sourceTree = "<group>"; };
6B3BE42A1E6217CB008D098A /* VLCImageButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCImageButton.h; sourceTree = "<group>"; };
......@@ -876,6 +882,10 @@
6B7F1FDE1F07DA920002BDD8 /* VLCHexNumberFormatter.m */,
6B3BE42A1E6217CB008D098A /* VLCImageButton.h */,
6B3BE42B1E6217CB008D098A /* VLCImageButton.m */,
6B0AB0EC1F1AC8B3003A1B4E /* VLCSlider.h */,
6B0AB0ED1F1AC8B3003A1B4E /* VLCSlider.m */,
6B0AB0EE1F1AC8B3003A1B4E /* VLCSliderCell.h */,
6B0AB0EF1F1AC8B3003A1B4E /* VLCSliderCell.m */,
6BF5C5051EFE7E58008A9C12 /* VLCTintedImageButtonCell.h */,
6BF5C5061EFE7E58008A9C12 /* VLCTintedImageButtonCell.m */,
1C67C8A61D58C0A40079E1C1 /* VLCAboutWindowController.h */,
......@@ -1846,7 +1856,7 @@
};
};
};
buildConfigurationList = C2F2A6EA09588F1B00018C74 /* Build configuration list for PBXProject "vlc" */;
buildConfigurationList = C2F2A6EA09588F1B00018C74 /* Build configuration list for PBXProject "VLC" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 1;
......@@ -1872,6 +1882,7 @@
buildActionMask = 2147483647;
files = (
6B81662C1EBFC38100C26F1B /* VLCUIWidgets.m in Sources */,
6B0AB0F11F1AC8B3003A1B4E /* VLCSliderCell.m in Sources */,
6B81662B1EBFC35D00C26F1B /* VLCVoutWindowController.m in Sources */,
6B8166291EBFC34300C26F1B /* VLCDefaultValueSlider.m in Sources */,
6B81662A1EBFC34300C26F1B /* VLCDefaultValueSliderCell.m in Sources */,
......@@ -1901,6 +1912,7 @@
1C3113961E508C6900D4DD76 /* applescript.m in Sources */,
1C3113981E508C6900D4DD76 /* VLCAudioEffectsWindowController.m in Sources */,
1C31139A1E508C6900D4DD76 /* VLCBookmarksWindowController.m in Sources */,
6B0AB0F01F1AC8B3003A1B4E /* VLCSlider.m in Sources */,
6BF5C5041EFE66EF008A9C12 /* VLCHUDTableView.m in Sources */,
6BBB05E01EEFF165003A1019 /* VLCHUDTableCornerView.m in Sources */,
1C31139D1E508C6900D4DD76 /* VLCControlsBarCommon.m in Sources */,
......@@ -2158,7 +2170,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Default;
};
C2F2A6EA09588F1B00018C74 /* Build configuration list for PBXProject "vlc" */ = {
C2F2A6EA09588F1B00018C74 /* Build configuration list for PBXProject "VLC" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C2F2A6EB09588F1B00018C74 /* Development */,
......
......@@ -98,7 +98,9 @@ libmacosx_plugin_la_SOURCES = \
gui/macosx/VLCImageButton.h gui/macosx/VLCImageButton.m \
gui/macosx/VLCTintedImageButtonCell.h gui/macosx/VLCTintedImageButtonCell.m \
gui/macosx/VLCTimeField.h gui/macosx/VLCTimeField.m \
gui/macosx/VLCHexNumberFormatter.h gui/macosx/VLCHexNumberFormatter.m
gui/macosx/VLCHexNumberFormatter.h gui/macosx/VLCHexNumberFormatter.m \
gui/macosx/VLCSlider.h gui/macosx/VLCSlider.m \
gui/macosx/VLCSliderCell.h gui/macosx/VLCSliderCell.m
# User interface compilation
......
/*****************************************************************************
* VLCSlider.h
*****************************************************************************
* Copyright (C) 2017 VLC authors and VideoLAN
* $Id$
*
* Authors: Marvin Scholz <epirat07 at gmail dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#import <Cocoa/Cocoa.h>
@interface VLCSlider : NSSlider
@property (nonatomic, getter=getIndefinite,setter=setIndefinite:) BOOL indefinite;
@end
/*****************************************************************************
* VLCSlider.m
*****************************************************************************
* Copyright (C) 2017 VLC authors and VideoLAN
* $Id$
*
* Authors: Marvin Scholz <epirat07 at gmail dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#import "VLCSlider.h"
#import "VLCSliderCell.h"
@implementation VLCSlider
// Workaround for 10.7
// http://stackoverflow.com/questions/3985816/custom-nsslidercell
- (void)setNeedsDisplayInRect:(NSRect)invalidRect {
[super setNeedsDisplayInRect:[self bounds]];
}
- (void)awakeFromNib {
[super awakeFromNib];
if(![self.cell isKindOfClass:[VLCSliderCell class]]) {
self.cell = [[VLCSliderCell alloc] init];
}
}
- (BOOL)getIndefinite
{
return [(VLCSliderCell*)[self cell] indefinite];
}
- (void)setIndefinite:(BOOL)indefinite
{
[(VLCSliderCell*)[self cell] setIndefinite:indefinite];
}
- (BOOL)isFlipped
{
return NO;
}
@end
/*****************************************************************************
* VLCSliderCell.h
*****************************************************************************
* Copyright (C) 2017 VLC authors and VideoLAN
* $Id$
*
* Authors: Marvin Scholz <epirat07 at gmail dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
@interface VLCSliderCell : NSSliderCell
// Colors
@property NSColor *gradientColor;
@property NSColor *gradientColor2;
@property NSColor *trackStrokeColor;
@property NSColor *filledTrackColor;
@property NSColor *knobFillColor;
@property NSColor *activeKnobFillColor;
@property NSColor *shadowColor;
@property NSColor *knobStrokeColor;
@property NSColor *highlightBackground;
// Gradients
@property NSGradient *trackGradient;
@property NSGradient *highlightGradient;
// Shadows
@property NSShadow *knobShadow;
@property NSInteger animationWidth;
@property (nonatomic, setter=setIndefinite:) BOOL indefinite;
@end
/*****************************************************************************
* VLCSliderCell.m
*****************************************************************************
* Copyright (C) 2017 VLC authors and VideoLAN
* $Id$
*
* Authors: Marvin Scholz <epirat07 at gmail dot com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#import "VLCSliderCell.h"
#import "CompatibilityFixes.h"
@interface VLCSliderCell () {
NSInteger _animationPosition;
double _lastTime;
double _deltaToLastFrame;
NSRect _lastKnobRect;
CVDisplayLinkRef _displayLink;
}
@end
@implementation VLCSliderCell
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
// Color Declarations
_gradientColor = [NSColor colorWithCalibratedRed: 0.663 green: 0.663 blue: 0.663 alpha: 1];
_gradientColor2 = [NSColor colorWithCalibratedRed: 0.749 green: 0.749 blue: 0.753 alpha: 1];
_trackStrokeColor = [NSColor colorWithCalibratedRed: 0.619 green: 0.624 blue: 0.623 alpha: 1];
_filledTrackColor = [NSColor colorWithCalibratedRed: 0.596 green: 0.596 blue: 0.596 alpha: 1];
_knobFillColor = [NSColor colorWithCalibratedRed: 1 green: 1 blue: 1 alpha: 1];
_activeKnobFillColor = [NSColor colorWithCalibratedRed: 0.95 green: 0.95 blue: 0.95 alpha: 1];
_shadowColor = [NSColor colorWithCalibratedRed: 0.32 green: 0.32 blue: 0.32 alpha: 1];
_knobStrokeColor = [NSColor colorWithCalibratedRed: 0.592 green: 0.596 blue: 0.596 alpha: 1];
// Gradient Declarations
_trackGradient = [[NSGradient alloc] initWithColorsAndLocations:
_gradientColor, 0.0,
[_gradientColor blendedColorWithFraction:0.5 ofColor:_gradientColor2], 0.60,
_gradientColor2, 1.0, nil];
// Shadow Declarations
_knobShadow = [[NSShadow alloc] init];
_knobShadow.shadowColor = _shadowColor;
_knobShadow.shadowOffset = NSMakeSize(0, 0);
_knobShadow.shadowBlurRadius = 2;
_highlightBackground = [NSColor colorWithCalibratedRed:0.20 green:0.55 blue:0.91 alpha:1.0];
NSColor *highlightAccent = [NSColor colorWithCalibratedRed:0.4588235294 green:0.7254901961 blue:0.9882352941 alpha:1.0];
_highlightGradient = [[NSGradient alloc] initWithColors:@[
_highlightBackground,
highlightAccent,
_highlightBackground
]];
_animationWidth = [[self controlView] bounds].size.width;
[self initDisplayLink];
}
return self;
}
- (void)dealloc
{
CVDisplayLinkRelease(_displayLink);
}
static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext)
{
CVTimeStamp inNowCopy = *inNow;
dispatch_async(dispatch_get_main_queue(), ^{
VLCSliderCell *sliderCell = (__bridge VLCSliderCell*)displayLinkContext;
[sliderCell displayLink:displayLink tickWithTime:&inNowCopy];
});
return kCVReturnSuccess;
}
- (void)displayLink:(CVDisplayLinkRef)displayLink tickWithTime:(const CVTimeStamp*)inNow
{
if (_lastTime == 0) {
_deltaToLastFrame = 0;
} else {
_deltaToLastFrame = (double)(inNow->videoTime - _lastTime) / inNow->videoTimeScale;
}
_lastTime = inNow->videoTime;
[self.controlView setNeedsDisplay:YES];
}
- (void)initDisplayLink
{
CVReturn ret = CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
if (ret != kCVReturnSuccess) {
// TODO: Handle error
return;
}
CVDisplayLinkSetOutputCallback(_displayLink, DisplayLinkCallback, (__bridge void*) self);
}
#pragma mark -
#pragma mark Normal slider drawing
- (void)drawKnob:(NSRect)knobRect
{
_lastKnobRect = knobRect;
// 10.7 - 10.10 hack
if (!OSX_YOSEMITE_AND_HIGHER)
knobRect.size.height += 1.5;
// Draw knob
NSBezierPath* knobPath = [NSBezierPath bezierPathWithOvalInRect:NSInsetRect(knobRect, 2.0, 2.0)];
if (self.isHighlighted) {
[_activeKnobFillColor setFill];
} else {
[_knobFillColor setFill];
}
[knobPath fill];
[_knobStrokeColor setStroke];
knobPath.lineWidth = 0.5;
[NSGraphicsContext saveGraphicsState];
if (self.isHighlighted)
[_knobShadow set];
[knobPath stroke];
[NSGraphicsContext restoreGraphicsState];
}
- (NSRect)barRectFlipped:(BOOL)flipped
{
return [[self controlView] bounds];
}
- (void)drawBarInside:(NSRect)rect flipped:(BOOL)flipped
{
// Inset rect
rect = NSInsetRect(rect, 1.0, 1.0);
// Empty Track Drawing
NSBezierPath* emptyTrackPath = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:3 yRadius:3];
[_trackGradient drawInBezierPath:emptyTrackPath angle:-90];
[_trackStrokeColor setStroke];
emptyTrackPath.lineWidth = 1;
[emptyTrackPath stroke];
// Calculate filled track
NSRect filledTrackRect = rect;
NSRect knobRect = [self knobRectFlipped:NO];
filledTrackRect.size.width = knobRect.origin.x + (self.knobThickness / 2);
// Filled Track Drawing
CGFloat filledTrackCornerRadius = 2;
NSRect filledTrackInnerRect = NSInsetRect(filledTrackRect, filledTrackCornerRadius, filledTrackCornerRadius);
NSBezierPath* filledTrackPath = [NSBezierPath bezierPathWithRoundedRect:filledTrackInnerRect
xRadius:filledTrackCornerRadius
yRadius:filledTrackCornerRadius];
[_filledTrackColor setFill];
[filledTrackPath fill];
}
#pragma mark -
#pragma mark Indefinite slider drawing
- (void)drawHighlightInRect:(NSRect)rect
{
[_highlightGradient drawInRect:rect angle:0];
}
- (void)drawHighlightBackgroundInRect:(NSRect)rect
{
rect = NSInsetRect(rect, 1.0, 1.0);
NSBezierPath *fullPath = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:2.0 yRadius:2.0];
[_highlightBackground setFill];
[fullPath fill];
}
- (void)drawAnimationInRect:(NSRect)rect
{
[self drawHighlightBackgroundInRect:rect];
[NSGraphicsContext saveGraphicsState];
rect = NSInsetRect(rect, 1.0, 1.0);
NSBezierPath *fullPath = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:2.0 yRadius:2.0];
[fullPath setClip];
// Use previously calculated position
rect.origin.x = _animationPosition;
// Calculate new position for next Frame
if (_animationPosition < (rect.size.width + _animationWidth)) {
_animationPosition += (rect.size.width + _animationWidth) * _deltaToLastFrame;
} else {
_animationPosition = -(_animationWidth);
}
rect.size.width = _animationWidth;
[self drawHighlightInRect:rect];
[NSGraphicsContext restoreGraphicsState];
_deltaToLastFrame = 0;
}
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
if (_indefinite)
return [self drawAnimationInRect:cellFrame];
[super drawWithFrame:cellFrame inView:controlView];
}
#pragma mark -
#pragma mark Animation handling
- (void)beginAnimating
{
CVReturn err = CVDisplayLinkStart(_displayLink);
if (err != kCVReturnSuccess) {
// TODO: Handle error
}
_animationPosition = -(_animationWidth);
[self setEnabled:NO];
}
- (void)endAnimating
{
CVDisplayLinkStop(_displayLink);
[self setEnabled:YES];
}
- (void)setIndefinite:(BOOL)indefinite
{
if (_indefinite == indefinite)
return;
if (indefinite)
[self beginAnimating];
else
[self endAnimating];
_indefinite = indefinite;
}
@end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment