-
Notifications
You must be signed in to change notification settings - Fork 135
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
1,238 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#if canImport(AppKit) && !targetEnvironment(macCatalyst) | ||
import AppKit | ||
|
||
extension NSAlert { | ||
/// Creates and returns a alert for displaying an alert using a data description. | ||
/// | ||
/// - Parameters: | ||
/// - state: A data description of the alert. | ||
/// - handler: A closure that is invoked with an action held in `state`. | ||
public convenience init<Action>( | ||
state: AlertState<Action>, | ||
handler: @escaping (_ action: Action?) -> Void | ||
) { | ||
self.init() | ||
self.messageText = String(state: state.title) | ||
state.message.map { self.informativeText = String(state: $0) } | ||
|
||
for button in state.buttons { | ||
addButton(button, action: handler) | ||
} | ||
} | ||
} | ||
|
||
extension NSAlert { | ||
public func addButton<Action>( | ||
_ buttonState: ButtonState<Action>, | ||
action handler: @escaping (_ action: Action?) -> Void = { (_: Never?) in } | ||
) { | ||
let button = addButton(withTitle: String(state: buttonState.label)) | ||
|
||
button.createActionProxyIfNeeded().addBindingAction { _ in | ||
buttonState.withAction(handler) | ||
} | ||
|
||
if buttonState.role == .destructive, #available(macOS 11.0, *) { | ||
button.hasDestructiveAction = true | ||
} | ||
|
||
if buttonState.role == .cancel { | ||
button.keyEquivalent = "\u{1b}" | ||
} | ||
|
||
if #available(macOS 12, *) { | ||
button.setAccessibilityLabel(buttonState.label.accessibilityLabel.map { String(state: $0) }) | ||
} | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#if canImport(AppKit) && !targetEnvironment(macCatalyst) | ||
|
||
import AppKit | ||
|
||
extension NSColorPanel: NSTargetActionProtocol { | ||
public var appkitNavigationTarget: AnyObject? { | ||
set { setTarget(newValue) } | ||
get { value(forKeyPath: "target") as? AnyObject } | ||
} | ||
|
||
public var appkitNavigationAction: Selector? { | ||
set { setAction(newValue) } | ||
get { value(forKeyPath: "action") as? Selector } | ||
} | ||
} | ||
|
||
extension NSColorPanel { | ||
/// Creates a new color panel and registers the binding against the | ||
/// selected color. | ||
/// | ||
/// - Parameters: | ||
/// - frame: The frame rectangle for the view, measured in points. | ||
/// - color: The binding to read from for the selected color, and write to when the | ||
/// selected color is changes. | ||
public convenience init(color: UIBinding<NSColor>) { | ||
self.init() | ||
bind(color: color) | ||
} | ||
|
||
/// Establishes a two-way connection between a binding and the color panel's selected color. | ||
/// | ||
/// - Parameter color: The binding to read from for the selected color, and write to | ||
/// when the selected color changes. | ||
/// - Returns: A cancel token. | ||
@discardableResult | ||
public func bind(color: UIBinding<NSColor>) -> ObserveToken { | ||
bind(color, to: \.color) | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#if canImport(AppKit) && !targetEnvironment(macCatalyst) | ||
import AppKit | ||
|
||
extension NSColorWell { | ||
/// Creates a new color well with the specified frame and registers the binding against the | ||
/// selected color. | ||
/// | ||
/// - Parameters: | ||
/// - frame: The frame rectangle for the view, measured in points. | ||
/// - color: The binding to read from for the selected color, and write to when the | ||
/// selected color is changes. | ||
public convenience init(frame: CGRect = .zero, color: UIBinding<NSColor>) { | ||
self.init(frame: frame) | ||
bind(color: color) | ||
} | ||
|
||
/// Establishes a two-way connection between a binding and the color well's selected color. | ||
/// | ||
/// - Parameter color: The binding to read from for the selected color, and write to | ||
/// when the selected color changes. | ||
/// - Returns: A cancel token. | ||
@discardableResult | ||
public func bind(color: UIBinding<NSColor>) -> ObserveToken { | ||
bind(color, to: \.color) | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#if canImport(AppKit) && !targetEnvironment(macCatalyst) | ||
|
||
import AppKit | ||
|
||
extension NSControl: NSTargetActionProtocol { | ||
public var appkitNavigationTarget: AnyObject? { | ||
set { target = newValue } | ||
get { target } | ||
} | ||
|
||
public var appkitNavigationAction: Selector? { | ||
set { action = newValue } | ||
get { action } | ||
} | ||
} | ||
|
||
extension NSControl { | ||
public convenience init(action: @escaping (Self) -> Void) { | ||
self.init(frame: .zero) | ||
createActionProxyIfNeeded().addAction { [weak self] _ in | ||
guard let self else { return } | ||
action(self) | ||
} | ||
} | ||
|
||
@discardableResult | ||
public func addAction(_ action: @escaping (NSControl) -> Void) -> UUID { | ||
createActionProxyIfNeeded().addAction { [weak self] _ in | ||
guard let self else { return } | ||
action(self) | ||
} | ||
} | ||
|
||
public func removeAction(for id: UUID) { | ||
createActionProxyIfNeeded().removeAction(for: id) | ||
} | ||
|
||
public func removeAllActions() { | ||
createActionProxyIfNeeded().removeAllActions() | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#if canImport(AppKit) && !targetEnvironment(macCatalyst) | ||
import AppKit | ||
|
||
extension NSDatePicker { | ||
/// Creates a new date picker with the specified frame and registers the binding against the | ||
/// selected date. | ||
/// | ||
/// - Parameters: | ||
/// - frame: The frame rectangle for the view, measured in points. | ||
/// - date: The binding to read from for the selected date, and write to when the selected | ||
/// date changes. | ||
public convenience init(frame: CGRect = .zero, date: UIBinding<Date>) { | ||
self.init(frame: frame) | ||
bind(date: date) | ||
} | ||
|
||
/// Establishes a two-way connection between a binding and the date picker's selected date. | ||
/// | ||
/// - Parameter date: The binding to read from for the selected date, and write to when the | ||
/// selected date changes. | ||
/// - Returns: A cancel token. | ||
@discardableResult | ||
public func bind(date: UIBinding<Date>) -> ObserveToken { | ||
bind(date, to: \.dateValue) | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#if canImport(AppKit) && !targetEnvironment(macCatalyst) | ||
|
||
import AppKit | ||
import SwiftNavigation | ||
|
||
extension NSFontManager: NSTargetActionProtocol, @unchecked Sendable { | ||
public var appkitNavigationTarget: AnyObject? { | ||
set { appkitNavigationDelegate.target = newValue } | ||
get { appkitNavigationDelegate.target } | ||
} | ||
|
||
public var appkitNavigationAction: Selector? { | ||
set { appkitNavigationDelegate.action = newValue } | ||
get { appkitNavigationDelegate.action } | ||
} | ||
|
||
private static let appkitNavigationDelegateKey = malloc(1)! | ||
|
||
private var appkitNavigationDelegate: Delegate { | ||
set { | ||
objc_setAssociatedObject(self, Self.appkitNavigationDelegateKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
get { | ||
if let delegate = objc_getAssociatedObject(self, Self.appkitNavigationDelegateKey) as? Delegate { | ||
return delegate | ||
} else { | ||
let delegate = Delegate() | ||
target = delegate | ||
self.appkitNavigationDelegate = delegate | ||
return delegate | ||
} | ||
} | ||
} | ||
|
||
private class Delegate: NSObject, NSFontChanging { | ||
var target: AnyObject? | ||
var action: Selector? | ||
|
||
func changeFont(_ sender: NSFontManager?) { | ||
if let action { | ||
NSApplication.shared.sendAction(action, to: target, from: sender) | ||
} | ||
} | ||
} | ||
} | ||
|
||
@MainActor | ||
extension NSFontManager { | ||
/// Creates a new date picker with the specified frame and registers the binding against the | ||
/// selected date. | ||
/// | ||
/// - Parameters: | ||
/// - frame: The frame rectangle for the view, measured in points. | ||
/// - date: The binding to read from for the selected date, and write to when the selected | ||
/// date changes. | ||
public convenience init(font: UIBinding<NSFont>) { | ||
self.init() | ||
bind(font: font) | ||
} | ||
|
||
/// Establishes a two-way connection between a binding and the date picker's selected date. | ||
/// | ||
/// - Parameter date: The binding to read from for the selected date, and write to when the | ||
/// selected date changes. | ||
/// - Returns: A cancel token. | ||
@discardableResult | ||
public func bind(font: UIBinding<NSFont>) -> ObserveToken { | ||
bind(font, to: \._selectedFont) | ||
} | ||
|
||
@objc private var _selectedFont: NSFont { | ||
set { setSelectedFont(newValue, isMultiple: false) } | ||
get { convert(.systemFont(ofSize: 0)) } | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#if canImport(AppKit) && !targetEnvironment(macCatalyst) | ||
|
||
import AppKit | ||
|
||
extension NSMenuItem: NSTargetActionProtocol, @unchecked Sendable { | ||
public var appkitNavigationTarget: AnyObject? { | ||
set { target = newValue } | ||
get { target } | ||
} | ||
|
||
public var appkitNavigationAction: Selector? { | ||
set { action = newValue } | ||
get { action } | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#if canImport(AppKit) && !targetEnvironment(macCatalyst) | ||
|
||
import AppKit | ||
|
||
extension NSPathControl { | ||
/// Creates a new path control with the specified frame and registers the binding against the | ||
/// selected url. | ||
/// | ||
/// - Parameters: | ||
/// - frame: The frame rectangle for the view, measured in points. | ||
/// - date: The binding to read from for the selected url, and write to when the selected | ||
/// url changes. | ||
public convenience init(frame: CGRect = .zero, date: UIBinding<URL?>) { | ||
self.init(frame: frame) | ||
bind(url: date) | ||
} | ||
|
||
/// Establishes a two-way connection between a binding and the path control's selected url. | ||
/// | ||
/// - Parameter url: The binding to read from for the selected url, and write to when the | ||
/// selected url changes. | ||
/// - Returns: A cancel token. | ||
@discardableResult | ||
public func bind(url: UIBinding<URL?>) -> ObserveToken { | ||
bind(url, to: \.url) | ||
} | ||
} | ||
|
||
#endif |
Oops, something went wrong.