Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more UIKit <-> AppKit compatibility to NSUI #1

Merged
merged 3 commits into from
Dec 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,39 @@ dependencies: [
```

## Types
All Types and their `UIKit` & `AppKit` correspondance are defined in the `Aliases.swift` file. That file only defines the
NSUI type corresponding to the proper platform.

Here's the current list of types supported in NSUI:
```
NSUIActivityIndicatorView
NSUIApplication
NSUIApplicationDelegate
NSUIApplicationDelegateAdaptor

// Collection Views
NSUICollectionDataSource
NSUICollectionView
NSUICollectionViewItem
NSUICollectionViewDelegate
NSUICollectionViewLayout
NSUICollectionViewFlowLayout
NSUICollectionViewLayoutAttributes
NSUICollectionViewDelegateFlowLayout

NSUIColor
NSUIEdgeInsets
NSUIFont
NSUIHostingController
NSUIImage
NSUILongPressGestureRecognizer
NSUINib
NSUIPasteboard
NSUIResponder
NSUITapGestureRecognizer
NSUITextStorageEditActions
NSUITextField
NSUITextFieldDelegate
NSUITextView
NSUIViewController
NSUIWorkspace
Expand All @@ -53,6 +73,33 @@ public protocol NSUIViewRepresentable {
}
```

## Conventions
NSUI is not a multi-platform framework to replace both UIKit and AppKit. As stated above, `NSUI` takes the stance that
the API from `UIKit` is the first-class citizen. However, in some cases, both AppKit and UIKit are very close to each other.

Let's take, for example, the `NSProgressIndicator` and `UIActivityIndicator` classes. To start the spinning indicator view, you need to
issue `startAnimating()` for UIKit and `startAnimation(sender:)` for AppKit.

In order to bridge that slight difference, a bridging function is created in the `Views.swift` file which looks like this:
```swift
extension NSUIActivityIndicator {
public func startAnimating() {
self.startAnimation(nil)
}

public func stopAnimating() {
self.stopAnimation(nil)
}
}
```
This extension is wrapped within a: `#if canImport(AppKit)` and provides the `UIKit` functional equivalent to the `AppKit` class.

## Enhancing `NSUI`
If you need to enhance `NSUI`, follow the following guidelines:
1- Check if the type you need is defined in the `Aliases.swift` file. If not, add it there
2- If your type, needs to supply a bridging `var` or `func`, define that in a proper swift file.
3- Always prioritize the `UIKit` naming scheme when defining new bridging `var` or `func`.

## Contributing and Collaboration

I would love to hear from you! Issues or pull requests work great. A [Discord server][discord] is also available for live help, but I have a strong bias towards answering in the form of documentation.
Expand Down
39 changes: 39 additions & 0 deletions Sources/NSUI/Aliases.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,35 @@ import SwiftUI
#if canImport(AppKit)
import AppKit

public typealias NSUIActivityIndicatorView = NSProgressIndicator
public typealias NSUIApplication = NSApplication
public typealias NSUIApplicationDelegate = NSApplicationDelegate
@available(macOS 11.0, *)
public typealias NSUIApplicationDelegateAdaptor = NSApplicationDelegateAdaptor

// Collection View
public typealias NSUICollectionDataSource = NSCollectionViewDataSource
public typealias NSUICollectionView = NSCollectionView
public typealias NSUICollectionViewItem = NSCollectionViewItem
public typealias NSUICollectionViewDelegate = NSCollectionViewDelegate
public typealias NSUICollectionViewLayout = NSCollectionViewLayout
public typealias NSUICollectionViewFlowLayout = NSCollectionViewFlowLayout
public typealias NSUICollectionViewLayoutAttributes = NSCollectionViewLayoutAttributes
public typealias NSUICollectionViewDelegateFlowLayout = NSCollectionViewDelegateFlowLayout

public typealias NSUIColor = NSColor
public typealias NSUIEdgeInsets = NSEdgeInsets
public typealias NSUIFont = NSFont
public typealias NSUIImage = NSImage
public typealias NSUIImageView = NSImageView
public typealias NSUILabel = NSTextField
public typealias NSUILongPressGestureRecognizer = NSPressGestureRecognizer
public typealias NSUINib = NSNib
public typealias NSUIPasteboard = NSPasteboard
public typealias NSUIResponder = NSResponder
public typealias NSUITapGestureRecognizer = NSClickGestureRecognizer
public typealias NSUITextField = NSTextField
public typealias NSUITextFieldDelegate = NSTextFieldDelegate
public typealias NSUITextView = NSTextView
public typealias NSUIView = NSView
public typealias NSUIViewController = NSViewController
Expand All @@ -22,17 +41,37 @@ public typealias NSUIWorkspace = NSWorkspace
#elseif canImport(UIKit)
import UIKit

public typealias NSUIActivityIndicatorView = UIActivityIndicatorView
public typealias NSUIApplication = UIApplication
public typealias NSUIApplicationDelegate = UIApplicationDelegate
@available(iOS 14.0, tvOS 14.0, *)
public typealias NSUIApplicationDelegateAdaptor = UIApplicationDelegateAdaptor

// Collection View
public typealias NSUICollectionDataSource = UICollectionViewDataSource
public typealias NSUICollectionView = UICollectionView
public typealias NSUICollectionViewItem = UICollectionViewCell
public typealias NSUICollectionViewDelegate = UICollectionViewDelegate
public typealias NSUICollectionViewLayout = UICollectionViewLayout
public typealias NSUICollectionViewFlowLayout = UICollectionViewFlowLayout
public typealias NSUICollectionViewLayoutAttributes = UICollectionViewLayoutAttributes
public typealias NSUICollectionViewDelegateFlowLayout = UICollectionViewDelegateFlowLayout

public typealias NSUIColor = UIColor
public typealias NSUIEdgeInsets = UIEdgeInsets
public typealias NSUIFont = UIFont
public typealias NSUIImage = UIImage
public typealias NSUIImageView = UIImageView
public typealias NSUILabel = UILabel
public typealias NSUILongPressGestureRecognizer = UILongPressGestureRecognizer
public typealias NSUINib = UINib

@available(tvOS, unavailable)
public typealias NSUIPasteboard = UIPasteboard
public typealias NSUIResponder = UIResponder
public typealias NSUITapGestureRecognizer = UITapGestureRecognizer
public typealias NSUITextField = UITextField
public typealias NSUITextFieldDelegate = UITextFieldDelegate
public typealias NSUITextView = UITextView
public typealias NSUIView = UIView
public typealias NSUIViewController = UIViewController
Expand Down
18 changes: 18 additions & 0 deletions Sources/NSUI/ImageView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import SwiftUI

#if canImport(AppKit)
public extension NSImageView {
func tintColor(color: NSUIColor) {
guard
let selfImage = self.image
else { return }
let image = NSImage(size: selfImage.size, flipped: false) { (rect) -> Bool in
color.set()
rect.fill()
selfImage.draw(in: rect, from: NSRect(origin: .zero, size: selfImage.size), operation: .destinationIn, fraction: 1.0)
return true
}
self.image = image
}
}
#endif
23 changes: 23 additions & 0 deletions Sources/NSUI/Label.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#if canImport(AppKit)
import AppKit

public extension NSUILabel {
var text: String {
get {
return stringValue
}
set {
stringValue = newValue
}
}
var textAlignment: NSTextAlignment {
get {
return alignment
}

set {
alignment = newValue
}
}
}
#endif
11 changes: 11 additions & 0 deletions Sources/NSUI/Views.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ extension NSUIResponder {
}
}

extension NSUIActivityIndicatorView {
public func startAnimating() {
self.startAnimation(nil)
}

public func stopAnimating() {
self.stopAnimation(nil)
}
}


#elseif canImport(UIKit)
import UIKit

Expand Down
Loading