├── screenshots └── custom-class.png ├── README.md ├── LICENSE └── ScrollableSlider.swift /screenshots/custom-class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thompsonate/Scrollable-NSSlider/HEAD/screenshots/custom-class.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Scrollable-NSSlider 2 | `ScrollableSlider` is a subclass of NSSlider that accepts input from scrolling events. Apple doesn't support this natively, so this subclass was created to allow for scrolling input. 3 | 4 | `ScrollableSlider` supports vertical, horizontal, and circular NSSliders. It also accounts for natural scroll direction, so you'll be scrolling in the right direction regardless of your settings. 5 | 6 | # How to implement 7 | 1. Add the [ScrollableSlider](ScrollableSlider.swift) class to your code. 8 | 1. For any slider you want to operate with scrolling input, select it in Interface Builder and set the custom class to ScrollableSlider. 9 | 1. Scroll! 10 | 11 |
12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /ScrollableSlider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollableSlider.swift 3 | // 4 | // Created by Nate Thompson on 10/24/17. 5 | // 6 | // 7 | 8 | 9 | import Cocoa 10 | 11 | class ScrollableSlider: NSSlider { 12 | override func scrollWheel(with event: NSEvent) { 13 | guard self.isEnabled else { return } 14 | 15 | let range = Float(self.maxValue - self.minValue) 16 | var delta = Float(0) 17 | 18 | // Allow horizontal scrolling on horizontal and circular sliders 19 | if _isVertical && self.sliderType == .linear { 20 | delta = Float(event.deltaY) 21 | } else if self.userInterfaceLayoutDirection == .rightToLeft { 22 | delta = Float(event.deltaY + event.deltaX) 23 | } else { 24 | delta = Float(event.deltaY - event.deltaX) 25 | } 26 | 27 | // Account for natural scrolling 28 | if event.isDirectionInvertedFromDevice { 29 | delta *= -1 30 | } 31 | 32 | let increment = range * delta / 100 33 | var value = self.floatValue + increment 34 | 35 | // Wrap around if slider is circular 36 | if self.sliderType == .circular { 37 | let minValue = Float(self.minValue) 38 | let maxValue = Float(self.maxValue) 39 | 40 | if value < minValue { 41 | value = maxValue - abs(increment) 42 | } else if value > maxValue { 43 | value = minValue + abs(increment) 44 | } 45 | } 46 | 47 | self.floatValue = value 48 | self.sendAction(self.action, to: self.target) 49 | } 50 | 51 | 52 | private var _isVertical: Bool { 53 | if #available(macOS 10.12, *) { 54 | return self.isVertical 55 | } else { 56 | // isVertical is an NSInteger in versions before 10.12 57 | return self.value(forKey: "isVertical") as! NSInteger == 1 58 | } 59 | } 60 | } 61 | --------------------------------------------------------------------------------