Skip to content

Commit

Permalink
Merge pull request #1 from kitwtnb/add-files
Browse files Browse the repository at this point in the history
Add files
  • Loading branch information
kitwtnb authored Aug 18, 2024
2 parents 6cff169 + 57b3391 commit 5d859c2
Show file tree
Hide file tree
Showing 17 changed files with 711 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,6 @@ fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output

.swiftpm/
.idea/
18 changes: 18 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// swift-tools-version: 5.10

import PackageDescription

let package = Package(
name: "OutLayout",
platforms: [
.iOS(.v12),
.macOS(.v11),
],
products: [
.library(name: "OutLayout", targets: ["OutLayout"]),
],
targets: [
.target(name: "OutLayout"),
.testTarget(name: "OutLayoutTests", dependencies: ["OutLayout"]),
]
)
65 changes: 64 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,64 @@
# OutLayout
# OutLayout

OutLayout is a lightweight wrapper for AutoLayout.
It prevents locking in libraries and allows for easy reverting to plain AutoLayout descriptions when no longer needed.

## Usage

```swift
import OutLayout

class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()

let backgroundView = UIView()
backgroundView.backgroundColor = .yellow
view.addSubview(backgroundView)

let view1 = UIView()
view1.backgroundColor = .red
view.addSubview(view1)

let view2 = UIView()
view2.backgroundColor = .blue
view.addSubview(view2)

let view3 = UIView()
view3.backgroundColor = .purple
view.addSubview(view3)

// Use OutLayout
backgroundView
.top(to: view)
.leading(to: view)
.trailing(to: view)
.bottom(to: view)

view1
.top(to: view, safeArea: true)
.leading(to: view, constant: 20)
.width(constant: 100)
.height(constant: 100)

view2
.centerX(to: view1.trailingAnchor)
.centerY(to: view1.bottomAnchor)
.width(to: view1)
.height(constant: 50)

view3
.centerX(to: view)
.centerY(to: view)
.width(to: view2)
.height(to: view2)
}
}
```

<img src=./doc/image/usage.png alt="usage" width="320">

## Installation

### Swift Package Manager
Add https://github.com/kitwtnb/OutLayout as a dependency.
9 changes: 9 additions & 0 deletions Sources/OutLayout/AutoLayoutResult.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
public struct _AutoLayoutResult: ViewHoldable {
let view: View

@MainActor
init(view: View) {
self.view = view
view.translatesAutoresizingMaskIntoConstraints = false
}
}
17 changes: 17 additions & 0 deletions Sources/OutLayout/ConstraintResult.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif

public struct _ConstraintResult: ViewHoldable {
public let constraint: NSLayoutConstraint
let view: View

@MainActor
init(constraint: NSLayoutConstraint, view: View) {
self.constraint = constraint
self.view = view
view.translatesAutoresizingMaskIntoConstraints = false
}
}
173 changes: 173 additions & 0 deletions Sources/OutLayout/Layoutable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif

public protocol _Layoutable {
@discardableResult
@MainActor
func top(to: View, constant: CGFloat, priority: Priority, safeArea: Bool) -> _AutoLayoutResult

@discardableResult
@MainActor
func top(to: NSLayoutYAxisAnchor, constant: CGFloat, priority: Priority) -> _AutoLayoutResult

@discardableResult
@MainActor
func bottom(to: View, constant: CGFloat, priority: Priority, safeArea: Bool) -> _AutoLayoutResult

@discardableResult
@MainActor
func bottom(to: NSLayoutYAxisAnchor, constant: CGFloat, priority: Priority) -> _AutoLayoutResult

@discardableResult
@MainActor
func leading(to: View, constant: CGFloat, priority: Priority, safeArea: Bool) -> _AutoLayoutResult

@discardableResult
@MainActor
func leading(to: NSLayoutXAxisAnchor, constant: CGFloat, priority: Priority) -> _AutoLayoutResult

@discardableResult
@MainActor
func trailing(to: View, constant: CGFloat, priority: Priority, safeArea: Bool) -> _AutoLayoutResult

@discardableResult
@MainActor
func trailing(to: NSLayoutXAxisAnchor, constant: CGFloat, priority: Priority) -> _AutoLayoutResult

@discardableResult
@MainActor
func centerX(to: View, constant: CGFloat, priority: Priority) -> _AutoLayoutResult

@discardableResult
@MainActor
func centerX(to: NSLayoutXAxisAnchor, constant: CGFloat, priority: Priority) -> _AutoLayoutResult

@discardableResult
@MainActor
func centerY(to: View, constant: CGFloat, priority: Priority) -> _AutoLayoutResult

@discardableResult
@MainActor
func centerY(to: NSLayoutYAxisAnchor, constant: CGFloat, priority: Priority) -> _AutoLayoutResult

@discardableResult
@MainActor
func width(to: View, constant: CGFloat, priority: Priority) -> _AutoLayoutResult

@discardableResult
@MainActor
func width(constant: CGFloat, priority: Priority) -> _AutoLayoutResult

@discardableResult
@MainActor
func height(to: View, constant: CGFloat, priority: Priority) -> _AutoLayoutResult

@discardableResult
@MainActor
func height(constant: CGFloat, priority: Priority) -> _AutoLayoutResult
}

extension _Layoutable {
@discardableResult
@MainActor
public func top(to view: View, constant: CGFloat = .zero, priority: Priority = .required, safeArea: Bool = false) -> _AutoLayoutResult {
top(to: safeArea ? view.safeAreaLayoutGuide.topAnchor : view.topAnchor, constant: constant, priority: priority)
}

@discardableResult
@MainActor
public func top(to: NSLayoutYAxisAnchor, constant: CGFloat = .zero, priority: Priority = .required) -> _AutoLayoutResult {
top(to: to, constant: constant, priority: priority)
}

@discardableResult
@MainActor
public func bottom(to view: View, constant: CGFloat = .zero, priority: Priority = .required, safeArea: Bool = false) -> _AutoLayoutResult {
bottom(to: safeArea ? view.safeAreaLayoutGuide.bottomAnchor : view.bottomAnchor, constant: constant, priority: priority)
}

@discardableResult
@MainActor
public func bottom(to: NSLayoutYAxisAnchor, constant: CGFloat = .zero, priority: Priority = .required) -> _AutoLayoutResult {
bottom(to: to, constant: constant, priority: priority)
}

@discardableResult
@MainActor
public func leading(to view: View, constant: CGFloat = .zero, priority: Priority = .required, safeArea: Bool = false) -> _AutoLayoutResult {
leading(to: safeArea ? view.safeAreaLayoutGuide.leadingAnchor : view.leadingAnchor, constant: constant, priority: priority)
}

@discardableResult
@MainActor
public func leading(to: NSLayoutXAxisAnchor, constant: CGFloat = .zero, priority: Priority = .required) -> _AutoLayoutResult {
leading(to: to, constant: constant, priority: priority)
}

@discardableResult
@MainActor
public func trailing(to view: View, constant: CGFloat = .zero, priority: Priority = .required, safeArea: Bool = false) -> _AutoLayoutResult {
trailing(to: safeArea ? view.safeAreaLayoutGuide.trailingAnchor : view.trailingAnchor, constant: constant, priority: priority)
}

@discardableResult
@MainActor
public func trailing(to: NSLayoutXAxisAnchor, constant: CGFloat = .zero, priority: Priority = .required) -> _AutoLayoutResult {
trailing(to: to, constant: constant, priority: priority)
}
}

extension _Layoutable {
@discardableResult
@MainActor
public func centerX(to view: View, constant: CGFloat = .zero, priority: Priority = .required) -> _AutoLayoutResult {
centerX(to: view.centerXAnchor, constant: constant, priority: priority)
}

@discardableResult
@MainActor
public func centerX(to: NSLayoutXAxisAnchor, constant: CGFloat = .zero, priority: Priority = .required) -> _AutoLayoutResult {
centerX(to: to, constant: constant, priority: priority)
}

@discardableResult
@MainActor
public func centerY(to view: View, constant: CGFloat = .zero, priority: Priority = .required) -> _AutoLayoutResult {
centerY(to: view.centerYAnchor, constant: constant, priority: priority)
}

@discardableResult
@MainActor
public func centerY(to: NSLayoutYAxisAnchor, constant: CGFloat = .zero, priority: Priority = .required) -> _AutoLayoutResult {
centerY(to: to, constant: constant, priority: priority)
}
}

extension _Layoutable {
@discardableResult
@MainActor
public func width(to: View, constant: CGFloat = .zero, priority: Priority = .required) -> _AutoLayoutResult {
width(to: to, constant: constant, priority: priority)
}

@discardableResult
@MainActor
public func width(constant: CGFloat, priority: Priority = .required) -> _AutoLayoutResult {
width(constant: constant, priority: priority)
}

@discardableResult
@MainActor
public func height(to: View, constant: CGFloat = .zero, priority: Priority = .required) -> _AutoLayoutResult {
height(to: to, constant: constant, priority: priority)
}

@discardableResult
@MainActor
public func height(constant: CGFloat, priority: Priority = .required) -> _AutoLayoutResult {
height(constant: constant, priority: priority)
}
}
21 changes: 21 additions & 0 deletions Sources/OutLayout/NSLayoutDimensionExt.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif

extension NSLayoutDimension {
func constraint(equalTo: NSLayoutAnchor<NSLayoutDimension>, constant: CGFloat, priority: Priority, isActive: Bool) -> NSLayoutConstraint {
let c = constraint(equalTo: equalTo, constant: constant)
c.priority = priority
c.isActive = isActive
return c
}

func constraint(equalToConstant: CGFloat, priority: Priority, isActive: Bool) -> NSLayoutConstraint {
let c = constraint(equalToConstant: equalToConstant)
c.priority = priority
c.isActive = isActive
return c
}
}
14 changes: 14 additions & 0 deletions Sources/OutLayout/NSLayoutXAxisAnchorExt.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif

extension NSLayoutXAxisAnchor {
func constraint(equalTo: NSLayoutAnchor<NSLayoutXAxisAnchor>, constant: CGFloat, priority: Priority, isActive: Bool) -> NSLayoutConstraint {
let c = constraint(equalTo: equalTo, constant: constant)
c.priority = priority
c.isActive = isActive
return c
}
}
14 changes: 14 additions & 0 deletions Sources/OutLayout/NSLayoutYAxisAnchorExt.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#if canImport(UIKit)
import UIKit
#else
import AppKit
#endif

extension NSLayoutYAxisAnchor {
func constraint(equalTo: NSLayoutAnchor<NSLayoutYAxisAnchor>, constant: CGFloat, priority: Priority, isActive: Bool) -> NSLayoutConstraint {
let c = constraint(equalTo: equalTo, constant: constant)
c.priority = priority
c.isActive = isActive
return c
}
}
9 changes: 9 additions & 0 deletions Sources/OutLayout/TypeAlias.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#if canImport(UIKit)
import UIKit
public typealias View = UIView
public typealias Priority = UILayoutPriority
#else
import AppKit
public typealias View = NSView
public typealias Priority = NSLayoutConstraint.Priority
#endif
Loading

0 comments on commit 5d859c2

Please sign in to comment.