|
// |
|
// DSFDelayedRepeatingButton.swift |
|
// |
|
// Created by Darren Ford on 16/1/21. |
|
// |
|
// MIT License |
|
// |
|
// Permission is hereby granted, free of charge, to any person obtaining a copy |
|
// of this software and associated documentation files (the "Software"), to deal |
|
// in the Software without restriction, including without limitation the rights |
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
// copies of the Software, and to permit persons to whom the Software is |
|
// furnished to do so, subject to the following conditions: |
|
// |
|
// The above copyright notice and this permission notice shall be included in all |
|
// copies or substantial portions of the Software. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
// SOFTWARE. |
|
// |
|
|
|
#if canImport(AppKit) && os(macOS) |
|
|
|
import AppKit |
|
|
|
/// A simple NSButton that supports a delayed button repeat if the user clicks and holds the button |
|
internal class DSFDelayedRepeatingButton: NSButton { |
|
|
|
private var eventTimer: Timer? |
|
|
|
deinit { |
|
self.eventTimer?.invalidate() |
|
self.eventTimer = nil |
|
} |
|
|
|
override func mouseDown(with _: NSEvent) { |
|
guard let w = self.window else { |
|
return |
|
} |
|
|
|
self.performClick(self) |
|
|
|
self.eventTimer = Timer.scheduledTimer( |
|
timeInterval: NSEvent.keyRepeatDelay, |
|
target: self, |
|
selector: #selector(self.initialTimerCallback), |
|
userInfo: "initial", |
|
repeats: false |
|
) |
|
|
|
RunLoop.current.add(self.eventTimer!, forMode: .eventTracking) |
|
|
|
var keepGoing = true |
|
while keepGoing { |
|
guard let theEvent = w.nextEvent(matching: [.leftMouseUp]) else { |
|
keepGoing = false |
|
break |
|
} |
|
|
|
switch theEvent.type { |
|
case .leftMouseUp: |
|
self.eventTimer?.invalidate() |
|
keepGoing = false |
|
default: |
|
break |
|
} |
|
} |
|
|
|
self.eventTimer?.invalidate() |
|
self.eventTimer = nil |
|
|
|
self.needsDisplay = true |
|
} |
|
|
|
@objc func initialTimerCallback(_ timer: Timer) { |
|
guard let which = timer.userInfo as? String else { |
|
return |
|
} |
|
|
|
if which == "initial" { |
|
// Remove the old timer first |
|
self.eventTimer?.invalidate() |
|
self.eventTimer = nil |
|
|
|
self.eventTimer = Timer.scheduledTimer( |
|
timeInterval: NSEvent.keyRepeatInterval, |
|
target: self, |
|
selector: #selector(self.initialTimerCallback), |
|
userInfo: "repeat", |
|
repeats: true |
|
) |
|
RunLoop.current.add(self.eventTimer!, forMode: .eventTracking) |
|
} |
|
|
|
self.sendAction(self.action, to: self.target) |
|
} |
|
} |
|
|
|
#endif |