// // UIView.swift // VDS // // Created by Matt Bruce on 11/17/22. // import Foundation import UIKit import VDSFormControlsTokens extension UIView { public func constraint(with identifier: String) -> NSLayoutConstraint? { return constraints.first { $0.identifier == identifier } } } //-------------------------------------------------- // MARK: - Pinning //-------------------------------------------------- extension UIView { @discardableResult public func pin(_ view: UIView, with edges: UIEdgeInsets = UIEdgeInsets.zero) -> Self { pinLeading(view.leadingAnchor, edges.left) pinTrailing(view.trailingAnchor, edges.right) pinTop(view.topAnchor, edges.top) pinBottom(view.bottomAnchor, edges.bottom) return self } @discardableResult public func pinToSuperView(_ edges: UIEdgeInsets = UIEdgeInsets.zero) -> Self { if let superview { pin(superview, with: edges) } return self } } //-------------------------------------------------- // MARK: - HeightAnchor //-------------------------------------------------- extension UIView { @discardableResult public func height(_ constant: CGFloat) -> Self { height(constant: constant) return self } @discardableResult public func heightGreaterThanEqualTo(_ constant: CGFloat) -> Self { heightGreaterThanEqualTo(constant: constant) return self } @discardableResult public func heightLessThanEqualTo(_ constant: CGFloat) -> Self { heightLessThanEqualTo(constant: constant) return self } @discardableResult public func height(constant: CGFloat) -> NSLayoutConstraint { heightAnchor.constraint(equalToConstant: constant).activate() } @discardableResult public func heightGreaterThanEqualTo(constant: CGFloat) -> NSLayoutConstraint { heightAnchor.constraint(greaterThanOrEqualToConstant: constant).activate() } @discardableResult public func heightLessThanEqualTo(constant: CGFloat) -> NSLayoutConstraint { heightAnchor.constraint(lessThanOrEqualToConstant: constant).activate() } } //-------------------------------------------------- // MARK: - WidthAnchor //-------------------------------------------------- extension UIView { @discardableResult public func width(_ constant: CGFloat) -> Self { width(constant: constant) return self } @discardableResult public func widthGreaterThanEqualTo(_ constant: CGFloat) -> Self { widthGreaterThanEqualTo(constant: constant) return self } @discardableResult public func widthLessThanEqualTo(_ constant: CGFloat) -> Self { widthLessThanEqualTo(constant: constant) return self } @discardableResult public func width(constant: CGFloat) -> NSLayoutConstraint { widthAnchor.constraint(equalToConstant: constant).activate() } @discardableResult public func widthGreaterThanEqualTo(constant: CGFloat) -> NSLayoutConstraint { widthAnchor.constraint(greaterThanOrEqualToConstant: constant).activate() } @discardableResult public func widthLessThanEqualTo(constant: CGFloat) -> NSLayoutConstraint { widthAnchor.constraint(lessThanOrEqualToConstant: constant).activate() } } //-------------------------------------------------- // MARK: - TopAnchor //-------------------------------------------------- extension UIView { @discardableResult public func pinTop(_ constant: CGFloat = 0.0) -> Self { return pinTop(nil, constant) } @discardableResult public func pinTop(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self { pinTop(anchor: anchor, constant: constant) return self } @discardableResult public func pinTopLessThanOrEqualTo(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self { pinBottomLessThanOrEqualTo(anchor: anchor, constant: constant) return self } @discardableResult public func pinTopGreaterThanOrEqualTo(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self { pinTopGreaterThanOrEqualTo(anchor: anchor, constant: constant) return self } @discardableResult public func pinTop(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? { let found: NSLayoutYAxisAnchor? = anchor ?? superview?.topAnchor guard let found else { return nil } return topAnchor.constraint(equalTo: found, constant: constant).activate() } @discardableResult public func pinTopLessThanOrEqualTo(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? { let found: NSLayoutYAxisAnchor? = anchor ?? superview?.topAnchor guard let found else { return nil } return topAnchor.constraint(lessThanOrEqualTo: found, constant: constant).activate() } @discardableResult public func pinTopGreaterThanOrEqualTo(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? { let found: NSLayoutYAxisAnchor? = anchor ?? superview?.topAnchor guard let found else { return nil } return topAnchor.constraint(greaterThanOrEqualTo: found, constant: constant).activate() } } //-------------------------------------------------- // MARK: - BottomAnchor //-------------------------------------------------- extension UIView { @discardableResult public func pinBottom(_ constant: CGFloat = 0.0) -> Self { return pinBottom(nil, constant) } @discardableResult public func pinBottom(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self { pinBottom(anchor: anchor, constant: constant) return self } @discardableResult public func pinBottomLessThanOrEqualTo(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self { pinBottomLessThanOrEqualTo(anchor: anchor, constant: constant) return self } @discardableResult public func pinBottomGreaterThanOrEqualTo(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self { pinBottomGreaterThanOrEqualTo(anchor: anchor, constant: constant) return self } @discardableResult public func pinBottom(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? { let found: NSLayoutYAxisAnchor? = anchor ?? superview?.bottomAnchor guard let found else { return nil } return bottomAnchor.constraint(equalTo: found, constant: -constant).activate() } @discardableResult public func pinBottomLessThanOrEqualTo(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? { let found: NSLayoutYAxisAnchor? = anchor ?? superview?.bottomAnchor guard let found else { return nil } return bottomAnchor.constraint(lessThanOrEqualTo: found, constant: -constant).activate() } @discardableResult public func pinBottomGreaterThanOrEqualTo(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? { let found: NSLayoutYAxisAnchor? = anchor ?? superview?.bottomAnchor guard let found else { return nil } return bottomAnchor.constraint(greaterThanOrEqualTo: found, constant: -constant).activate() } } //-------------------------------------------------- // MARK: - LeadingAnchor //-------------------------------------------------- extension UIView { @discardableResult public func pinLeading(_ constant: CGFloat = 0.0) -> Self { return pinLeading(nil, constant) } @discardableResult public func pinLeading(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self { pinLeading(anchor: anchor, constant: constant) return self } @discardableResult public func pinLeadingLessThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self { pinLeadingLessThanOrEqualTo(anchor: anchor, constant: constant) return self } @discardableResult public func pinLeadingGreaterThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self { pinLeadingGreaterThanOrEqualTo(anchor: anchor, constant: constant) return self } @discardableResult public func pinLeading(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? { let found: NSLayoutXAxisAnchor? = anchor ?? superview?.leadingAnchor guard let found else { return nil } return leadingAnchor.constraint(equalTo: found, constant: constant).activate() } @discardableResult public func pinLeadingLessThanOrEqualTo(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? { let found: NSLayoutXAxisAnchor? = anchor ?? superview?.leadingAnchor guard let found else { return nil } return leadingAnchor.constraint(lessThanOrEqualTo: found, constant: constant).activate() } @discardableResult public func pinLeadingGreaterThanOrEqualTo(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? { let found: NSLayoutXAxisAnchor? = anchor ?? superview?.leadingAnchor guard let found else { return nil } return leadingAnchor.constraint(greaterThanOrEqualTo: found, constant: constant).activate() } } //-------------------------------------------------- // MARK: - TrailingAnchor //-------------------------------------------------- extension UIView { @discardableResult public func pinTrailing(_ constant: CGFloat = 0.0) -> Self { pinTrailing(nil, constant) } @discardableResult public func pinTrailing(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self { pinTrailing(anchor: anchor, constant: constant) return self } @discardableResult public func pinTrailingLessThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self { pinTrailingLessThanOrEqualTo(anchor: anchor, constant: constant) return self } @discardableResult public func pinTrailingGreaterThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self { pinTrailingGreaterThanOrEqualTo(anchor: anchor, constant: constant) return self } @discardableResult public func pinTrailing(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? { let found: NSLayoutXAxisAnchor? = anchor ?? superview?.trailingAnchor guard let found else { return nil } return trailingAnchor.constraint(equalTo: found, constant: -constant).activate() } @discardableResult public func pinTrailingLessThanOrEqualTo(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? { let found: NSLayoutXAxisAnchor? = anchor ?? superview?.trailingAnchor guard let found else { return nil } return trailingAnchor.constraint(lessThanOrEqualTo: found, constant: -constant).activate() } @discardableResult public func pinTrailingGreaterThanOrEqualTo(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? { let found: NSLayoutXAxisAnchor? = anchor ?? superview?.trailingAnchor guard let found else { return nil } return trailingAnchor.constraint(greaterThanOrEqualTo: found, constant: -constant).activate() } } extension NSLayoutConstraint { @discardableResult public func activate() -> Self{ isActive = true return self } @discardableResult public func deactivate() -> Self{ isActive = false return self } public class Container { public var topConstraint: NSLayoutConstraint? public var leadingConstraint: NSLayoutConstraint? public var trailingConstraint: NSLayoutConstraint? public var bottomConstraint: NSLayoutConstraint? public var widthConstraint: NSLayoutConstraint? public var heightConstraint: NSLayoutConstraint? public var isActive: Bool = false { didSet{ topConstraint?.isActive = isActive bottomConstraint?.isActive = isActive leadingConstraint?.isActive = isActive trailingConstraint?.isActive = isActive heightConstraint?.isActive = isActive widthConstraint?.isActive = isActive } } public init(){} } }