Skip to content
This repository has been archived by the owner on Apr 18, 2024. It is now read-only.

Commit

Permalink
Merge pull request #32 from hainayanda/shortcuts
Browse files Browse the repository at this point in the history
Added Shortcuts for more cleaner code
  • Loading branch information
hainayanda authored Jan 14, 2023
2 parents 6931cf8 + a52edbc commit f46baa5
Show file tree
Hide file tree
Showing 40 changed files with 2,006 additions and 1,230 deletions.
4 changes: 2 additions & 2 deletions Draftsman.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Pod::Spec.new do |s|

# s.public_header_files = 'Pod/Classes/**/*.h'
# s.frameworks = 'UIKit', 'MapKit'
s.dependency 'Clavier', '~> 2.0.1'
s.dependency 'Builder', '~> 1.0.4'
s.dependency 'Clavier', '~> 2.0.3'
s.dependency 'Builder', '~> 1.1.0'
s.swift_version = '5.5'
end
2 changes: 1 addition & 1 deletion Draftsman/Classes/Anchors/Base/DimensionAnchor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ extension DimensionAnchor where Root.Layout: UIView, Root: ViewPlanBuilder {
create(.lessThanOrEqual, to: otherAnchor)
}

func create(_ relation: NSLayoutConstraint.Relation, to otherAnchor: NSLayoutDimension) -> DimensionAnchorRelation<Root> {
func create(_ relation: NSLayoutConstraint.Relation, to otherAnchor: NSLayoutDimension) -> DimensionAnchorRelation<Root> {
.init(
root: root,
firstAnchor: anchor.extractable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class ConstraintBuilderRootRecoverable<Root: ViewPlanBuilder & LayoutAnch
public typealias Layout = Root.Layout
/// To avoid retain cycle
var root: Root!

@inlinable public var insertablePlans: [ViewDraft] {
backToRoot { $0.insertablePlans }
}
Expand All @@ -41,6 +42,7 @@ public class ConstraintBuilderRootRecoverable<Root: ViewPlanBuilder & LayoutAnch
}

extension ConstraintBuilderRootRecoverable where Root: ViewDraft {
@discardableResult
@inlinable public func insert(@LayoutPlan _ layouter: () -> ViewPlan) -> Root {
backToRoot { $0.insert(layouter) }
}
Expand All @@ -56,6 +58,7 @@ extension ConstraintBuilderRootRecoverable where Root: ViewDraft {
}

extension ConstraintBuilderRootRecoverable where Root: StackDraft {
@discardableResult
@inlinable public func insertStacked(@LayoutPlan _ layouter: () -> ViewPlan) -> Root {
backToRoot { $0.insertStacked(layouter) }
}
Expand Down
5 changes: 5 additions & 0 deletions Draftsman/Classes/Draft/LayoutDraft.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import Foundation
#if canImport(UIKit)
import UIKit
import Clavier

open class LayoutDraft<View: UIView>: ViewPlanBuilder, ViewDraft {
public var underlyingView: View
Expand All @@ -20,6 +21,7 @@ open class LayoutDraft<View: UIView>: ViewPlanBuilder, ViewDraft {

public init(view: View, plans: [ViewDraft] = []) {
self.underlyingView = view
view.useAppleKeyboardLayoutGuideIfAvailable = false
super.init(plans: plans)
}

Expand Down Expand Up @@ -47,6 +49,7 @@ open class LayoutDraft<View: UIView>: ViewPlanBuilder, ViewDraft {
return constraints
}

@discardableResult
public func insert(@LayoutPlan _ layouter: () -> ViewPlan) -> Self {
let viewPlan = layouter()
plans.append(contentsOf: viewPlan.insertablePlans)
Expand All @@ -64,6 +67,7 @@ open class LayoutDraft<View: UIView>: ViewPlanBuilder, ViewDraft {
guard let stack = context.currentView as? StackCompatible else { return [] }
return buildSubview(plans: stackPlans, for: context) {
stack.addArrangedSubview($0)
($0 as? SpacerView)?.apply(axis: stack.axis)
}
}
}
Expand All @@ -75,6 +79,7 @@ extension LayoutDraft: StackDraft where View: StackCompatible {
self.stackPlans = stackPlans
}

@discardableResult
public func insertStacked(@LayoutPlan _ layouter: () -> ViewPlan) -> Self {
let viewPlan = layouter()
stackPlans.append(contentsOf: viewPlan.insertablePlans)
Expand Down
6 changes: 6 additions & 0 deletions Draftsman/Classes/Draft/LayoutPlan.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ import Foundation
#if canImport(UIKit)
import UIKit

extension Array: PlanComponent where Element: PlanComponent {
public var insertablePlans: [ViewDraft] {
flatMap { $0.insertablePlans }
}
}

@resultBuilder
public struct LayoutPlan {
public typealias Expression = PlanComponent?
Expand Down
126 changes: 126 additions & 0 deletions Draftsman/Classes/Utilities/CustomView/ScrollableStackView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
//
// File.swift
//
//
// Created by Nayanda Haberty on 9/1/23.
//

import Foundation
#if canImport(UIKit)
import UIKit

public class ScrollableStackView: UIScrollView, Planned {
let alignment: UIStackView.Alignment
let spacing: CGFloat
public var axis: NSLayoutConstraint.Axis {
didSet {
stackView.axis = axis
}
}

lazy var stackView: UIStackView = UIStackView(
axis: axis,
distribution: .equalSpacing,
alignment: alignment,
spacing: spacing
)

public override var subviews: [UIView] {
var allSubviews = super.subviews
allSubviews.append(contentsOf: stackView.subviews)
return allSubviews
}

@LayoutPlan
public var viewPlan: ViewPlan {
if axis == .vertical {
stackView.drf
.width.equal(with: .parent)
.edges.equal(with: .parent)
} else {
stackView.drf
.height.equal(with: .parent)
.edges.equal(with: .parent)
}
}

public override init(frame: CGRect) {
self.alignment = .center
self.spacing = .zero
self.axis = .vertical
super.init(frame: frame)
}

public init(
frame: CGRect = .zero,
axis: NSLayoutConstraint.Axis,
margins: UIEdgeInsets? = nil,
alignment: UIStackView.Alignment = .center,
spacing: CGFloat = .zero) {
self.axis = axis
self.alignment = alignment
self.spacing = spacing
super.init(frame: frame)
if let margins = margins {
self.stackView.layoutMargins = margins
self.stackView.isLayoutMarginsRelativeArrangement = true
}
applyPlan()
}

required init?(coder: NSCoder) {
self.axis = .vertical
self.alignment = .center
self.spacing = .zero
super.init(coder: coder)
applyPlan()
}
}

extension ScrollableStackView: StackCompatible {

public override var layoutMargins: UIEdgeInsets {
get {
stackView.layoutMargins
}
set {
stackView.layoutMargins = newValue
}
}

public var isLayoutMarginsRelativeArrangement: Bool {
get {
stackView.isLayoutMarginsRelativeArrangement
}
set {
stackView.isLayoutMarginsRelativeArrangement = newValue
}
}

public var arrangedSubviews: [UIView] {
stackView.arrangedSubviews
}

public func addArrangedSubview(_ view: UIView) {
stackView.addArrangedSubview(view)
}

public func removeArrangedSubview(_ view: UIView) {
stackView.removeArrangedSubview(view)
}

public func insertArrangedSubview(_ view: UIView, at stackIndex: Int) {
stackView.insertArrangedSubview(view, at: stackIndex)
}

@available(iOS 11.0, *)
public func setCustomSpacing(_ spacing: CGFloat, after arrangedSubview: UIView) {
stackView.setCustomSpacing(spacing, after: arrangedSubview)
}

@available(iOS 11.0, *)
public func customSpacing(after arrangedSubview: UIView) -> CGFloat {
stackView.customSpacing(after: arrangedSubview)
}
}
#endif
96 changes: 96 additions & 0 deletions Draftsman/Classes/Utilities/CustomView/SpacerView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//
// SpacerView.swift
// Draftsman
//
// Created by Nayanda Haberty on 11/1/23.
//

import Foundation
#if canImport(UIKit)
import UIKit

public class SpacerView: UIView {

let dimension: CGFloat?
var spaceConstraint: NSLayoutConstraint?

public init(_ dimension: CGFloat) {
self.dimension = dimension
super.init(frame: .zero)
self.backgroundColor = .clear
}

public init() {
self.dimension = nil
super.init(frame: .zero)
self.backgroundColor = .clear
}

func apply(axis: NSLayoutConstraint.Axis) {
spaceConstraint?.isActive = false
guard let dimension = self.dimension else {
super.setContentCompressionResistancePriority(.defaultLow, for: axis)
super.setContentHuggingPriority(.defaultLow, for: axis)
super.setContentCompressionResistancePriority(
defaultContentCompressionResistancePriority(for: axis.crossAxis),
for: axis.crossAxis
)
super.setContentHuggingPriority(
defaultContentHuggingPriority(for: axis.crossAxis),
for: axis.crossAxis
)
return
}
switch axis {
case .horizontal:
spaceConstraint = widthAnchor.constraint(greaterThanOrEqualToConstant: dimension)
spaceConstraint?.isActive = true
case .vertical:
spaceConstraint = heightAnchor.constraint(greaterThanOrEqualToConstant: dimension)
spaceConstraint?.isActive = true
@unknown default:
break
}
}

required init?(coder: NSCoder) {
self.dimension = nil
super.init(coder: coder)
self.backgroundColor = .clear
}

private var userContentHuggingPriority: [NSLayoutConstraint.Axis: UILayoutPriority] = [:]
public override func setContentHuggingPriority(_ priority: UILayoutPriority, for axis: NSLayoutConstraint.Axis) {
super.setContentHuggingPriority(priority, for: axis)
userContentHuggingPriority[axis] = priority
}

private var userContentCompressionResistancePriority: [NSLayoutConstraint.Axis: UILayoutPriority] = [:]
public override func setContentCompressionResistancePriority(_ priority: UILayoutPriority, for axis: NSLayoutConstraint.Axis) {
super.setContentCompressionResistancePriority(priority, for: axis)
userContentCompressionResistancePriority[axis] = priority
}

private func defaultContentHuggingPriority(for axis: NSLayoutConstraint.Axis) -> UILayoutPriority {
userContentHuggingPriority[axis.crossAxis] ?? UILayoutPriority(250)
}

private func defaultContentCompressionResistancePriority(for axis: NSLayoutConstraint.Axis) -> UILayoutPriority {
userContentCompressionResistancePriority[axis.crossAxis] ?? UILayoutPriority(750)
}

}

extension NSLayoutConstraint.Axis {
var crossAxis: NSLayoutConstraint.Axis {
switch self {
case .horizontal:
return .vertical
case .vertical:
return .horizontal
@unknown default:
return self
}
}
}
#endif
29 changes: 5 additions & 24 deletions Draftsman/Classes/Utilities/Extensions/UIView+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public extension UIStackView {

@inlinable convenience init(
axis: NSLayoutConstraint.Axis,
margins: UIEdgeInsets? = nil,
distribution: UIStackView.Distribution = .fill,
alignment: UIStackView.Alignment = .fill,
spacing: CGFloat = .zero) {
Expand All @@ -43,33 +44,13 @@ public extension UIStackView {
self.distribution = distribution
self.alignment = alignment
self.spacing = spacing
if let margins = margins {
self.layoutMargins = margins
self.isLayoutMarginsRelativeArrangement = true
}
}
}

@inlinable public func VStackView(
distribution: UIStackView.Distribution = .fill,
alignment: UIStackView.Alignment = .fill,
spacing: CGFloat = .zero) -> UIStackView {
.init(
axis: .vertical,
distribution: distribution,
alignment: alignment,
spacing: spacing
)
}

@inlinable public func HStackView(
distribution: UIStackView.Distribution = .fill,
alignment: UIStackView.Alignment = .fill,
spacing: CGFloat = .zero) -> UIStackView {
.init(
axis: .horizontal,
distribution: distribution,
alignment: alignment,
spacing: spacing
)
}

public protocol CellWithContentView: UIView {
var contentView: UIView { get }
}
Expand Down
Loading

0 comments on commit f46baa5

Please sign in to comment.