[vlc-devel] [PATCH 1/2] macosx: Add VLCDefaultValueSlider

Marvin Scholz epirat07 at gmail.com
Sun Dec 11 18:21:04 CET 2016


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.
---
 .../package/macosx/vlc.xcodeproj/project.pbxproj   |  12 ++
 modules/gui/macosx/Makefile.am                     |   4 +-
 modules/gui/macosx/VLCDefaultValueSlider.h         |  62 ++++++++
 modules/gui/macosx/VLCDefaultValueSlider.m         |  83 +++++++++++
 modules/gui/macosx/VLCDefaultValueSliderCell.h     |  58 ++++++++
 modules/gui/macosx/VLCDefaultValueSliderCell.m     | 156 +++++++++++++++++++++
 6 files changed, 374 insertions(+), 1 deletion(-)
 create mode 100644 modules/gui/macosx/VLCDefaultValueSlider.h
 create mode 100644 modules/gui/macosx/VLCDefaultValueSlider.m
 create mode 100644 modules/gui/macosx/VLCDefaultValueSliderCell.h
 create mode 100644 modules/gui/macosx/VLCDefaultValueSliderCell.m

diff --git a/extras/package/macosx/vlc.xcodeproj/project.pbxproj b/extras/package/macosx/vlc.xcodeproj/project.pbxproj
index 0dfd087..f986c83 100644
--- a/extras/package/macosx/vlc.xcodeproj/project.pbxproj
+++ b/extras/package/macosx/vlc.xcodeproj/project.pbxproj
@@ -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 */,
diff --git a/modules/gui/macosx/Makefile.am b/modules/gui/macosx/Makefile.am
index 2a0fcc8..9f5cc4f 100644
--- a/modules/gui/macosx/Makefile.am
+++ b/modules/gui/macosx/Makefile.am
@@ -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
diff --git a/modules/gui/macosx/VLCDefaultValueSlider.h b/modules/gui/macosx/VLCDefaultValueSlider.h
new file mode 100644
index 0000000..4a9ab7c
--- /dev/null
+++ b/modules/gui/macosx/VLCDefaultValueSlider.h
@@ -0,0 +1,62 @@
+/*****************************************************************************
+ * 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.
+ */
+ at interface VLCDefaultValueSlider : NSSlider
+
+/**
+ Indicates if the slider is scrollable with the mouse or trackpad scrollwheel.
+ */
+ at property (readwrite) BOOL isScrollable;
+
+/**
+ Sets the default value to which the slider will snap and draw a tickmark for.
+ 
+ \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;
+
+/**
+ Unsets the default value
+ 
+ \note Internally this sets the defaultValue to \c DBL_MAX
+ */
+- (void)unsetDefaultValue;
+
+/**
+ Get the default value
+ 
+ \note It the returned value is \c DBL_MAX, there is no defaultValue set.
+ */
+- (double)defaultValue;
+
+ at end
diff --git a/modules/gui/macosx/VLCDefaultValueSlider.m b/modules/gui/macosx/VLCDefaultValueSlider.m
new file mode 100644
index 0000000..e10c5e5
--- /dev/null
+++ b/modules/gui/macosx/VLCDefaultValueSlider.m
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ * 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"
+
+ at 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];
+}
+
+- (void)unsetDefaultValue
+{
+    [(VLCDefaultValueSliderCell *)self.cell unsetDefaultValue];
+}
+
+- (double)defaultValue
+{
+    return [(VLCDefaultValueSliderCell *)self.cell defaultValue];
+}
+
+ at end
diff --git a/modules/gui/macosx/VLCDefaultValueSliderCell.h b/modules/gui/macosx/VLCDefaultValueSliderCell.h
new file mode 100644
index 0000000..1aae9b0
--- /dev/null
+++ b/modules/gui/macosx/VLCDefaultValueSliderCell.h
@@ -0,0 +1,58 @@
+/*****************************************************************************
+ * 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.
+ */
+ at interface VLCDefaultValueSliderCell : NSSliderCell
+
+/**
+ Indicates if a tickmark should be drawn for the \c defaultValue
+ */
+ at property (readwrite) BOOL drawTickMarkForDefault;
+
+/**
+ Indicates if the slider knob should snap to the \c defaultValue
+ */
+ at property (readwrite) BOOL snapsToDefault;
+
+- (void)setDefaultValue:(double)value;
+- (void)unsetDefaultValue;
+
+- (double)defaultValue;
+
+/**
+ 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;
+
+ at end
diff --git a/modules/gui/macosx/VLCDefaultValueSliderCell.m b/modules/gui/macosx/VLCDefaultValueSliderCell.m
new file mode 100644
index 0000000..f2fbbda
--- /dev/null
+++ b/modules/gui/macosx/VLCDefaultValueSliderCell.m
@@ -0,0 +1,156 @@
+/*****************************************************************************
+ * VLCDefaultValueSliderCell.m: 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 "VLCDefaultValueSliderCell.h"
+
+ at interface VLCDefaultValueSliderCell (){
+    double _defaultDoubleValue;
+    CGFloat _defaultPosition;
+    CGFloat _isRTL;
+}
+ at end
+
+ at implementation VLCDefaultValueSliderCell
+
+#pragma mark -
+#pragma mark Public interface
+
+- (instancetype)initWithCoder:(NSCoder *)coder
+{
+    self = [super initWithCoder:coder];
+    if (self) {
+        _defaultDoubleValue = DBL_MAX;
+        _isRTL = ([self userInterfaceLayoutDirection] == NSUserInterfaceLayoutDirectionRightToLeft);
+    }
+    return self;
+}
+
+- (void)setDefaultValue:(double)value
+{
+    if (_defaultDoubleValue == DBL_MAX) {
+        _drawTickMarkForDefault = YES;
+        _snapsToDefault = YES;
+    }
+    _defaultDoubleValue = value;
+    _defaultPosition = [self pointForValue:_defaultDoubleValue];
+}
+
+- (void)unsetDefaultValue
+{
+    _defaultDoubleValue = DBL_MAX;
+    _drawTickMarkForDefault = NO;
+    _snapsToDefault = NO;
+}
+
+- (double)defaultValue
+{
+    return _defaultDoubleValue;
+}
+
+- (void)drawDefaultTickMarkWithFrame:(NSRect)rect
+{
+    [[NSColor grayColor] setFill];
+    NSRectFill(rect);
+}
+
+#pragma mark -
+#pragma mark Internal helpers
+
+- (CGFloat)pointForValue:(double)value
+{
+    CGFloat sliderRange;
+    NSRect cellFrame = self.controlView.frame;
+    CGFloat defaultRelative = (self.maxValue - self.minValue) / (value - self.minValue);
+    if (self.isVertical)
+        sliderRange = cellFrame.size.height - self.knobThickness;
+    else
+        sliderRange = cellFrame.size.width - self.knobThickness;
+    CGFloat sliderOrigin = self.knobThickness / 2.0;
+    CGFloat point = 1.0 / defaultRelative * sliderRange + sliderOrigin;
+
+    return point;
+}
+
+#pragma mark -
+#pragma mark Overwritten super methods
+
+- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
+{
+    // Do all other drawing
+    [super drawWithFrame:cellFrame inView:controlView];
+
+    // Draw default tickmark
+    if (_drawTickMarkForDefault) {
+        CGFloat tickThickness = 1.0;
+        NSRect tickFrame = cellFrame;
+        if (self.isVertical) {
+            tickFrame.origin.y = (tickFrame.size.height - _defaultPosition);
+            tickFrame.origin.y -= tickThickness / 2;
+            tickFrame.size.height = tickThickness;
+        } else {
+            tickFrame.origin.x = (_isRTL) ? (tickFrame.size.width - _defaultPosition) : _defaultPosition;
+            tickFrame.origin.x -= tickThickness / 2;
+            tickFrame.size.width = tickThickness;
+        }
+
+        [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 = YES;
+    if (oldValue > newValue) {
+        sliderMovingForward = NO;
+    }
+
+    // Calculate snap-threshhold
+    double range = self.maxValue - self.minValue;
+    double thresh = (range * 0.01) * 5;
+
+    // Snap to default value
+    if (ABS(newValue - _defaultDoubleValue) < thresh && _snapsToDefault) {
+        if (sliderMovingForward && newValue > _defaultDoubleValue) {
+            [self setDoubleValue: _defaultDoubleValue];
+        } else if (!sliderMovingForward && newValue < _defaultDoubleValue) {
+            [self setDoubleValue: _defaultDoubleValue];
+        }
+    }
+
+    return result;
+}
+
+ at end
-- 
2.9.3 (Apple Git-75)



More information about the vlc-devel mailing list