diff --git a/VDS/Protocols/LayoutConstraintable.swift b/VDS/Protocols/LayoutConstraintable.swift index 3e40885b..3661bae0 100644 --- a/VDS/Protocols/LayoutConstraintable.swift +++ b/VDS/Protocols/LayoutConstraintable.swift @@ -631,6 +631,130 @@ extension LayoutConstraintable { return centerYAnchor.constraint(greaterThanOrEqualTo: found, constant: -constant).with { $0.priority = priority; $0.isActive = true } } } + +// alignment +public enum LayoutAlignment: String, CaseIterable { + case fill + case leading + case top + case center + case trailing + case bottom +} + +public enum LayoutDistribution: String, CaseIterable { + case fill + case fillProportionally +} + +extension LayoutConstraintable { + public func removeConstraints() { + guard let view = self as? UIView, let superview = view.superview else { return } + + // Remove all existing constraints on the containerView + let superviewConstraints = superview.constraints + for constraint in superviewConstraints { + if constraint.firstItem as? UIView == view + || constraint.secondItem as? UIView == view { + superview.removeConstraint(constraint) + } + } + } + + public func applyAlignment(_ alignment: LayoutAlignment, edges: UIEdgeInsets = UIEdgeInsets.zero) { + guard let superview = superview else { return } + + removeConstraints() + + switch alignment { + case .fill: + pinToSuperView(edges) + + case .leading: + pinTop(edges.top) + pinLeading(edges.left) + pinTrailingLessThanOrEqualTo(anchor: superview.trailingAnchor, constant: edges.right) + pinBottom(edges.bottom) + + case .trailing: + pinTop(edges.top) + pinLeadingGreaterThanOrEqualTo(anchor: superview.leadingAnchor, constant: edges.left) + pinTrailing(edges.right) + pinBottom(edges.bottom) + + case .top: + pinTop(edges.top) + pinLeadingGreaterThanOrEqualTo(anchor: superview.leadingAnchor, constant: edges.left) + pinTrailingLessThanOrEqualTo(anchor: superview.trailingAnchor, constant: edges.right) + pinBottomLessThanOrEqualTo(anchor: superview.bottomAnchor, constant: edges.bottom) + + case .bottom: + pinTopGreaterThanOrEqualTo(anchor: superview.topAnchor, constant: edges.top) + pinLeadingGreaterThanOrEqualTo(anchor: superview.leadingAnchor, constant: edges.left) + pinTrailingLessThanOrEqualTo(anchor: superview.trailingAnchor, constant: edges.right) + pinBottom(edges.bottom) + + case .center: + pinCenterX() + pinTop(edges.top) + pinLeadingGreaterThanOrEqualTo(anchor: superview.leadingAnchor, constant: edges.left) + pinTrailingLessThanOrEqualTo(anchor: superview.trailingAnchor, constant: edges.right) + pinBottom(edges.bottom) + + } + } + + // Method to check if the view is pinned to its superview + public func isPinnedToSuperview() -> Bool { + isPinnedVerticallyToSuperview() && isPinnedHorizontallyToSuperview() + } + + public func isPinnedHorizontallyToSuperview() -> Bool { + guard let view = self as? UIView, let superview = view.superview else { return false } + let constraints = superview.constraints + var leadingPinned = false + var trailingPinned = false + + for constraint in constraints { + if (constraint.firstItem as? UIView == view && constraint.firstAttribute == .leading && constraint.relation == .equal && constraint.secondItem as? UIView == superview) || + (constraint.secondItem as? UIView == view && constraint.secondAttribute == .leading && constraint.relation == .equal && constraint.firstItem as? UIView == superview) || + (constraint.firstItem as? UIView == view && constraint.firstAttribute == .left && constraint.relation == .equal && constraint.secondItem as? UIView == superview) || + (constraint.secondItem as? UIView == view && constraint.secondAttribute == .left && constraint.relation == .equal && constraint.firstItem as? UIView == superview) { + leadingPinned = true + } + if (constraint.firstItem as? UIView == view && constraint.firstAttribute == .trailing && constraint.relation == .equal && constraint.secondItem as? UIView == superview) || + (constraint.secondItem as? UIView == view && constraint.secondAttribute == .trailing && constraint.relation == .equal && constraint.firstItem as? UIView == superview) || + (constraint.firstItem as? UIView == view && constraint.firstAttribute == .right && constraint.relation == .equal && constraint.secondItem as? UIView == superview) || + (constraint.secondItem as? UIView == view && constraint.secondAttribute == .right && constraint.relation == .equal && constraint.firstItem as? UIView == superview) { + trailingPinned = true + } + } + + return leadingPinned && trailingPinned + } + + public func isPinnedVerticallyToSuperview() -> Bool { + guard let view = self as? UIView, let superview = view.superview else { return false } + let constraints = superview.constraints + var topPinned = false + var bottomPinned = false + + for constraint in constraints { + if (constraint.firstItem as? UIView == view && constraint.firstAttribute == .top && constraint.relation == .equal && constraint.secondItem as? UIView == superview) || + (constraint.secondItem as? UIView == view && constraint.secondAttribute == .top && constraint.relation == .equal && constraint.firstItem as? UIView == superview) { + topPinned = true + } + if (constraint.firstItem as? UIView == view && constraint.firstAttribute == .bottom && constraint.relation == .equal && constraint.secondItem as? UIView == superview) || + (constraint.secondItem as? UIView == view && constraint.secondAttribute == .bottom && constraint.relation == .equal && constraint.firstItem as? UIView == superview) { + bottomPinned = true + } + } + + return topPinned && bottomPinned + } +} + + //-------------------------------------------------- // MARK: - Implementations //--------------------------------------------------