Commit d986f8ab authored by Marvin Scholz's avatar Marvin Scholz

macosx: Add VLCDefaultValueSlider

This is a new VLCDefaultSlider which allows setting a default
value, to which the knob will snap and a tick mark will be drawn for.
It's useful in VLC for things like volume sliders, which have a
default value (100%) to which we want the slider to snap.
Additionally this class is controllable with the scrollwheel by default.
parent 3b4bd994
......@@ -419,6 +419,8 @@
6B3F8D2F1CE58E0E002A4998 /* VLCPreviousTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 6B3F8D2B1CE58E0E002A4998 /* VLCPreviousTemplate.pdf */; };
6B3F8D311CE5CC21002A4998 /* VLCStatusBarIcon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 6B3F8D301CE5CC21002A4998 /* VLCStatusBarIcon.pdf */; };
6B3F8D331CE5CD57002A4998 /* VLCShuffleTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 6B3F8D321CE5CD57002A4998 /* VLCShuffleTemplate.pdf */; };
6B6A499E1DFD9B23009128AC /* VLCDefaultValueSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B6A499B1DFD9B23009128AC /* VLCDefaultValueSlider.m */; };
6B6A499F1DFD9B23009128AC /* VLCDefaultValueSliderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B6A499D1DFD9B23009128AC /* VLCDefaultValueSliderCell.m */; };
6B846FE41CF5D88C00112E54 /* VLCHUDButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B846FDD1CF5D88C00112E54 /* VLCHUDButtonCell.m */; };
6B846FE51CF5D88C00112E54 /* VLCHUDCheckboxCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B846FDF1CF5D88C00112E54 /* VLCHUDCheckboxCell.m */; };
6B846FE61CF5D88C00112E54 /* VLCHUDRadiobuttonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B846FE11CF5D88C00112E54 /* VLCHUDRadiobuttonCell.m */; };
......@@ -1125,6 +1127,10 @@
6B3F8D2B1CE58E0E002A4998 /* VLCPreviousTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = VLCPreviousTemplate.pdf; path = Resources/vlcmenubaricon/VLCPreviousTemplate.pdf; sourceTree = "<group>"; };
6B3F8D301CE5CC21002A4998 /* VLCStatusBarIcon.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = VLCStatusBarIcon.pdf; path = Resources/vlcmenubaricon/VLCStatusBarIcon.pdf; sourceTree = "<group>"; };
6B3F8D321CE5CD57002A4998 /* VLCShuffleTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = VLCShuffleTemplate.pdf; path = Resources/vlcmenubaricon/VLCShuffleTemplate.pdf; sourceTree = "<group>"; };
6B6A499A1DFD9B23009128AC /* VLCDefaultValueSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCDefaultValueSlider.h; path = ../../../modules/gui/macosx/VLCDefaultValueSlider.h; sourceTree = "<group>"; };
6B6A499B1DFD9B23009128AC /* VLCDefaultValueSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCDefaultValueSlider.m; path = ../../../modules/gui/macosx/VLCDefaultValueSlider.m; sourceTree = "<group>"; };
6B6A499C1DFD9B23009128AC /* VLCDefaultValueSliderCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCDefaultValueSliderCell.h; path = ../../../modules/gui/macosx/VLCDefaultValueSliderCell.h; sourceTree = "<group>"; };
6B6A499D1DFD9B23009128AC /* VLCDefaultValueSliderCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCDefaultValueSliderCell.m; path = ../../../modules/gui/macosx/VLCDefaultValueSliderCell.m; sourceTree = "<group>"; };
6B846FDC1CF5D88C00112E54 /* VLCHUDButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCHUDButtonCell.h; path = ../../../modules/gui/macosx/VLCHUDButtonCell.h; sourceTree = "<group>"; };
6B846FDD1CF5D88C00112E54 /* VLCHUDButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCHUDButtonCell.m; path = ../../../modules/gui/macosx/VLCHUDButtonCell.m; sourceTree = "<group>"; };
6B846FDE1CF5D88C00112E54 /* VLCHUDCheckboxCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCHUDCheckboxCell.h; path = ../../../modules/gui/macosx/VLCHUDCheckboxCell.h; sourceTree = "<group>"; };
......@@ -1763,6 +1769,10 @@
6B846FE81CF5D89500112E54 /* HUD UI Classes */,
5CCED71414C0D4A90057F8D1 /* VLCUIWidgets.h */,
5CCED71514C0D4A90057F8D1 /* VLCUIWidgets.m */,
6B6A499A1DFD9B23009128AC /* VLCDefaultValueSlider.h */,
6B6A499B1DFD9B23009128AC /* VLCDefaultValueSlider.m */,
6B6A499C1DFD9B23009128AC /* VLCDefaultValueSliderCell.h */,
6B6A499D1DFD9B23009128AC /* VLCDefaultValueSliderCell.m */,
E0C2583E161B593D00185AAD /* VLCVoutWindowController.h */,
E0C2583F161B593D00185AAD /* VLCVoutWindowController.m */,
E06CF7F416020F6200C698B7 /* Windows.h */,
......@@ -3556,6 +3566,7 @@
6B846FE51CF5D88C00112E54 /* VLCHUDCheckboxCell.m in Sources */,
1CCB5F6A1A62A724004C3E90 /* VLCExtensionsDialogProvider.h in Sources */,
7DBB06641CC2314D004C74D2 /* caopengllayer.m in Sources */,
6B6A499E1DFD9B23009128AC /* VLCDefaultValueSlider.m in Sources */,
1CCB5F6B1A62A724004C3E90 /* VLCExtensionsDialogProvider.m in Sources */,
1CCB5F6C1A62A724004C3E90 /* VLCExtensionsManager.h in Sources */,
1CCB5F6D1A62A724004C3E90 /* VLCExtensionsManager.m in Sources */,
......@@ -3582,6 +3593,7 @@
1C67C8A81D58C0A40079E1C1 /* VLCAboutWindowController.m in Sources */,
1CCB5F801A62A724004C3E90 /* VLCPlaylistInfo.m in Sources */,
1CCB5F811A62A724004C3E90 /* prefs_widgets.h in Sources */,
6B6A499F1DFD9B23009128AC /* VLCDefaultValueSliderCell.m in Sources */,
1CCB5F821A62A724004C3E90 /* prefs_widgets.m in Sources */,
1CCB5F831A62A724004C3E90 /* prefs.h in Sources */,
1CCB5F841A62A724004C3E90 /* prefs.m in Sources */,
......
......@@ -88,4 +88,6 @@ libmacosx_plugin_la_SOURCES = \
VLCResumeDialogController.h VLCResumeDialogController.m \
VLCTrackSynchronizationWindowController.h VLCTrackSynchronizationWindowController.m \
VLCVideoEffectsWindowController.h VLCVideoEffectsWindowController.m \
VLCFSPanelController.h VLCFSPanelController.m
VLCFSPanelController.h VLCFSPanelController.m \
VLCDefaultValueSlider.h VLCDefaultValueSlider.m \
VLCDefaultValueSliderCell.h VLCDefaultValueSliderCell.m
/*****************************************************************************
* VLCDefaultValueSlider.h: Custom NSSlider which allows a defaultValue
*****************************************************************************
* Copyright (C) 2016 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>
/**
\c VLCDefaultValueSlider is a NSSlider subclass that allows setting
a \c defaultValue which gets a tickmark and the knob snaps to that
default value. Additionally a VLCDefaultValueSlider can be adjusted
with the mouse scroll wheel, if enabled.
*/
@interface VLCDefaultValueSlider : NSSlider
/**
Indicates if the slider is scrollable with the mouse or trackpad scrollwheel.
*/
@property (readwrite) BOOL isScrollable;
/**
Sets the default value to which the slider will snap and draw a tickmark for.
To unset the defaultValue, set it to \c DBL_MAX
\note value must be in the value range of the slider and be smaller than \c DBL_MAX
\param value The default value
*/
- (void)setDefaultValue:(double)value;
/**
Get the default value
\note It the returned value is \c DBL_MAX, there is no defaultValue set.
*/
- (double)defaultValue;
@end
/*****************************************************************************
* VLCDefaultValueSlider.m: Custom NSSlider which allows a defaultValue
*****************************************************************************
* Copyright (C) 2016 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 "VLCDefaultValueSlider.h"
#import "VLCDefaultValueSliderCell.h"
@implementation VLCDefaultValueSlider
- (instancetype)initWithCoder:(NSCoder *)coder
{
if ([coder isKindOfClass: [NSKeyedUnarchiver class]]) {
NSKeyedUnarchiver *keyedUnarchiver = (id)coder;
NSString *oldClass = NSStringFromClass([self.superclass cellClass]);
[keyedUnarchiver setClass:[VLCDefaultValueSliderCell class] forClassName:oldClass];
}
self = [super initWithCoder:coder];
if (self) {
_isScrollable = YES;
}
return self;
}
- (void)scrollWheel:(NSEvent *)event
{
if (!_isScrollable)
return [super scrollWheel:event];
double increment;
CGFloat deltaY = [event scrollingDeltaY];
double range = [self maxValue] - [self minValue];
// Scroll less for high precision, else it's too fast
if (event.hasPreciseScrollingDeltas) {
increment = (range * 0.002) * deltaY;
} else {
if (deltaY == 0.0)
return;
increment = (range * 0.01 * deltaY);
}
// If scrolling is inversed, increment in other direction
if (!event.isDirectionInvertedFromDevice)
increment = -increment;
[self setDoubleValue:self.doubleValue - increment];
[self sendAction:self.action to:self.target];
}
- (void)setDefaultValue:(double)value
{
[(VLCDefaultValueSliderCell *)self.cell setDefaultValue:value];
}
- (double)defaultValue
{
return [(VLCDefaultValueSliderCell *)self.cell defaultValue];
}
@end
/*****************************************************************************
* VLCDefaultValueSliderCell.h: SliderCell subclass for VLCDefaultValueSlider
*****************************************************************************
* Copyright (C) 2016 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>
/**
\c VLCDefaultValueSliderCell is the cell use by the
\c VLCDefaultValueSlider class.
*/
@interface VLCDefaultValueSliderCell : NSSliderCell
/**
Indicates if a tickmark should be drawn for the \c defaultValue
*/
@property (readwrite) BOOL drawTickMarkForDefault;
/**
Indicates if the slider knob should snap to the \c defaultValue
*/
@property (readwrite) BOOL snapsToDefault;
/**
The default value of the slider
\note It may not be equal to \c DBL_MAX, as this is the value
that it should be set to, if no defaultValue is desired.
*/
@property (getter=defaultValue, setter=setDefaultValue:) double defaultValue;
/**
Color of the default tick mark
*/
@property (getter=defaultTickMarkColor, setter=setDefaultTickMarkColor:) NSColor *defaultTickMarkColor;
/**
Draws the tick mark for the \c defaultValue in the
given rect.
\note Override this in a subclass if you need to customize the
tickmark that is drawn for the \c defaultValue
\param rect The rect in which the tickMark should be drawn
*/
- (void)drawDefaultTickMarkWithFrame:(NSRect)rect;
@end
/*****************************************************************************
* VLCDefaultValueSliderCell.m: SliderCell subclass for VLCDefaultValueSlider
*****************************************************************************
* Copyright (C) 2016 VLC authors and VideoLAN
* $Id$
*
* Authors: Marvin Scholz <epirat07 -at- gmail -dot- com>
*
* This file uses parts of code from the GNUstep NSSliderCell code:
*
* Copyright (C) 1996,1999 Free Software Foundation, Inc.
* Author: Ovidiu Predescu <ovidiu@net-community.com>
* Date: September 1997
* Rewrite: Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Date: 1999
*
* 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 "VLCDefaultValueSliderCell.h"
@interface VLCDefaultValueSliderCell (){
BOOL _isRTL;
BOOL _isFlipped;
double _defaultValue;
NSColor *_defaultTickMarkColor;
}
@end
@implementation VLCDefaultValueSliderCell
#pragma mark -
#pragma mark Public interface
- (instancetype)init
{
self = [super init];
if (self) {
[self setupSelf];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self setupSelf];
}
return self;
}
- (void)setDefaultValue:(double)value
{
if (value > _maxValue || value < _minValue)
value = DBL_MAX;
if (_defaultValue == DBL_MAX && value != DBL_MAX) {
_drawTickMarkForDefault = YES;
_snapsToDefault = YES;
} else if (value == DBL_MAX) {
_drawTickMarkForDefault = NO;
_snapsToDefault = NO;
}
_defaultValue = value;
[[self controlView] setNeedsDisplay:YES];
}
- (double)defaultValue
{
return _defaultValue;
}
- (void)setDefaultTickMarkColor:(NSColor *)color
{
_defaultTickMarkColor = color;
[[self controlView] setNeedsDisplay:YES];
}
- (NSColor *)defaultTickMarkColor
{
return _defaultTickMarkColor;
}
- (void)drawDefaultTickMarkWithFrame:(NSRect)rect
{
[_defaultTickMarkColor setFill];
NSRectFill(rect);
}
#pragma mark -
#pragma mark Internal helpers
- (void)setupSelf
{
_defaultValue = DBL_MAX;
_isRTL = ([self userInterfaceLayoutDirection] == NSUserInterfaceLayoutDirectionRightToLeft);
_isFlipped = [[self controlView] isFlipped];
_defaultTickMarkColor = [NSColor grayColor];
}
/*
* Adapted from GNUstep NSSliderCell
* - (NSRect)knobRectFlipped:(BOOL)flipped
*
* Calculates the knobRect for a given position
* This is later used to draw the default tick mark in the center of
* where the knob would be, when it is at the default value.
*/
- (NSRect)knobRectFlipped:(BOOL)flipped forValue:(double)doubleValue
{
NSRect superRect = [super knobRectFlipped:flipped];
NSPoint origin = _trackRect.origin;
NSSize size = superRect.size;
if ([self isVertical] && flipped) {
doubleValue = _maxValue + _minValue - doubleValue;
}
doubleValue = (doubleValue - _minValue) / (_maxValue - _minValue);
if ([self isVertical] == YES) {
origin.x = superRect.origin.x;
origin.y += (_trackRect.size.height - size.height) * doubleValue;
} else {
origin.x += ((_trackRect.size.width - size.width) * doubleValue);
origin.y = superRect.origin.y;
}
return NSMakeRect(origin.x, origin.y, size.width, size.height);
}
#pragma mark -
#pragma mark Overwritten super methods
- (NSRect)knobRectFlipped:(BOOL)flipped
{
return [self knobRectFlipped:flipped forValue:[self doubleValue]];
}
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
// Do all other drawing
[super drawWithFrame:cellFrame inView:controlView];
// Default tick mark
if (_drawTickMarkForDefault && _defaultValue != DBL_MAX) {
// Calculate rect for default tick mark
CGFloat tickThickness = 1.0;
NSRect tickFrame = [self knobRectFlipped:_isFlipped
forValue:_defaultValue];
if ([self isVertical]) {
CGFloat mid = NSMidY(tickFrame);
tickFrame.origin.x = cellFrame.origin.x;
tickFrame.origin.y = mid - tickThickness/2.0;
tickFrame.size.width = cellFrame.size.width;
tickFrame.size.height = tickThickness;
} else {
CGFloat mid = NSMidX(tickFrame);
tickFrame.origin.x = mid - tickThickness/2.0;
tickFrame.origin.y = cellFrame.origin.y;
tickFrame.size.width = tickThickness;
tickFrame.size.height = cellFrame.size.height;
}
// Draw default tick mark
[self drawDefaultTickMarkWithFrame:tickFrame];
}
// Redraw knob
[super drawKnob];
}
- (BOOL)continueTracking:(NSPoint)lastPoint at:(NSPoint)currentPoint inView:(NSView *)controlView
{
double oldValue = [self doubleValue];
BOOL result = [super continueTracking:lastPoint at:currentPoint inView:controlView];
double newValue = [self doubleValue];
// If no change, nothing to do.
if (newValue == oldValue)
return result;
// Determine in which direction slider is moving
BOOL sliderMovingForward = (oldValue > newValue) ? NO : YES;
// Calculate snap-threshhold
double range = self.maxValue - self.minValue;
double thresh = (range * 0.01) * 7;
// Snap to default value
if (ABS(newValue - _defaultValue) < thresh && _snapsToDefault) {
if (sliderMovingForward && newValue > _defaultValue) {
[self setDoubleValue:_defaultValue];
} else if (!sliderMovingForward && newValue < _defaultValue) {
[self setDoubleValue:_defaultValue];
}
}
return result;
}
@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