Skip to content

Add isIncludedInPinLayoutSizeCalculation property to Layoutable #268

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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1367,17 +1367,17 @@ The property expose the `UIKit` value [`UIView.keyboardLayoutGuide`](https://dev
<a name="wrapContent"></a>
## WrapContent

The following methods are useful to adjust view's width and/or height to wrap all its subviews. These methods also adjust subviews position to create a tight wrap.
The following methods are useful to adjust view's width and/or height to wrap all its subviews that are included in the layout. These methods also adjust subviews position to create a tight wrap.

**Methods:**

* **`wrapContent()`**
**`wrapContent(padding: CGFloat)`**
**`wrapContent(padding: UIEdgeInsets)`**
Adjust the view's width and height to wrap all its subviews. The method also adjusts subviews's position to create a tight wrap. It is also possible to specify an optional padding around all subviews.
Adjust the view's width and height to wrap all its subviews that are included in the layout. The method also adjusts subviews's position to create a tight wrap. It is also possible to specify an optional padding around all subviews.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add an URL link that point to the documentation of the new property for the string are included in the layout

* **`wrapContent(:WrapType)`**
**`wrapContent(:WrapType, padding: CGFloat)`** **`wrapContent(:WrapType, padding: UIEdgeInsets)`**
Adjust the view's width AND/OR height to wrap all its subviews. Accept a WrapType parameter to define the wrapping type. It is also possible to specify an optional padding around all subviews.
Adjust the view's width AND/OR height to wrap all its subviews that are included in the layout. Accept a WrapType parameter to define the wrapping type. It is also possible to specify an optional padding around all subviews.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here


**Types:**

Expand Down
13 changes: 13 additions & 0 deletions Sources/Extensions/CALayer+PinLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
import QuartzCore

extension CALayer: Layoutable {
private struct pinlayoutAssociatedKeys {
static var pinlayoutIsIncludedInPinLayoutSizeCalculation = UnsafeMutablePointer<Int8>.allocate(capacity: 1)
}

public typealias PinView = CALayer

public var superview: CALayer? {
Expand All @@ -38,6 +42,15 @@ extension CALayer: Layoutable {
return PinLayout(view: self, keepTransform: false)
}

public var isIncludedInPinLayoutSizeCalculation: Bool {
get {
return objc_getAssociatedObject(self, &pinlayoutAssociatedKeys.pinlayoutIsIncludedInPinLayoutSizeCalculation) as? Bool ?? true
}
set {
objc_setAssociatedObject(self, &pinlayoutAssociatedKeys.pinlayoutIsIncludedInPinLayoutSizeCalculation, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}

public func getRect(keepTransform: Bool) -> CGRect {
if keepTransform {
/*
Expand Down
13 changes: 13 additions & 0 deletions Sources/Extensions/NSView+PinLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import Foundation
import AppKit

extension NSView: Layoutable {
private struct pinlayoutAssociatedKeys {
static var pinlayoutIsIncludedInPinLayoutSizeCalculation = UnsafeMutablePointer<Int8>.allocate(capacity: 1)
}

public typealias PinView = NSView

public var pin: PinLayout<NSView> {
Expand All @@ -37,6 +41,15 @@ extension NSView: Layoutable {
return PinLayoutObjCImpl(view: self, keepTransform: true)
}

public var isIncludedInPinLayoutSizeCalculation: Bool {
get {
return objc_getAssociatedObject(self, &pinlayoutAssociatedKeys.pinlayoutIsIncludedInPinLayoutSizeCalculation) as? Bool ?? true
}
set {
objc_setAssociatedObject(self, &pinlayoutAssociatedKeys.pinlayoutIsIncludedInPinLayoutSizeCalculation, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}

public func getRect(keepTransform: Bool) -> CGRect {
if let superview = superview, !superview.isFlipped {
var flippedRect = frame
Expand Down
12 changes: 11 additions & 1 deletion Sources/Extensions/UIView+PinLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ extension UIView: Layoutable, SizeCalculable {
return PinLayoutObjCImpl(view: self, keepTransform: true)
}

public var isIncludedInPinLayoutSizeCalculation: Bool {
get {
return objc_getAssociatedObject(self, &pinlayoutAssociatedKeys.pinlayoutIsIncludedInPinLayoutSizeCalculation) as? Bool ?? true
}
set {
objc_setAssociatedObject(self, &pinlayoutAssociatedKeys.pinlayoutIsIncludedInPinLayoutSizeCalculation, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}

public func getRect(keepTransform: Bool) -> CGRect {
guard !Pin.autoSizingInProgress || autoSizingRect == nil else { return autoSizingRect ?? CGRect.zero }

Expand Down Expand Up @@ -95,6 +104,7 @@ extension UIView: Layoutable, SizeCalculable {

extension UIView: AutoSizeCalculable {
private struct pinlayoutAssociatedKeys {
static var pinlayoutIsIncludedInPinLayoutSizeCalculation = UnsafeMutablePointer<Int8>.allocate(capacity: 1)
static var pinlayoutAutoSizingRect = UnsafeMutablePointer<Int8>.allocate(capacity: 1)
static var pinlayoutAutoSizingRectWithMargins = UnsafeMutablePointer<Int8>.allocate(capacity: 1)
}
Expand Down Expand Up @@ -133,7 +143,7 @@ extension UIView: AutoSizeCalculable {

layoutClosure()

let boundingRect = subviews.compactMap({ $0.autoSizingRectWithMargins }).reduce(CGRect.zero) { (result: CGRect, autoSizingRect: CGRect) -> CGRect in
let boundingRect = subviewsIncludedInSizeCalculation.compactMap({ $0.autoSizingRectWithMargins }).reduce(CGRect.zero) { (result: CGRect, autoSizingRect: CGRect) -> CGRect in
return result.union(autoSizingRect)
}

Expand Down
13 changes: 13 additions & 0 deletions Sources/Layoutable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,23 @@ public protocol Layoutable: AnyObject, Equatable, CustomDebugStringConvertible {
var superview: PinView? { get }
var subviews: [PinView] { get }

/// A Boolean value that determines whether the view is included in the PinLayout's size calculation.
///
/// An excluded view does not take up space in the layout
/// when using `wrapContent(_:padding:_:)` or `autoSizeThatFits(_:layoutClosure:)`.
/// The default value is `true`.
var isIncludedInPinLayoutSizeCalculation: Bool { get set }

func getRect(keepTransform: Bool) -> CGRect
func setRect(_ rect: CGRect, keepTransform: Bool)

func convert(_ point: CGPoint, to view: PinView?) -> CGPoint

func isLTR() -> Bool
}

extension Layoutable {
var subviewsIncludedInSizeCalculation: [PinView] {
return subviews.filter(\.isIncludedInPinLayoutSizeCalculation)
}
}
22 changes: 11 additions & 11 deletions Sources/PinLayout+WrapContent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ import AppKit

extension PinLayout {
/**
Adjust the view's width & height to wrap all its subviews. The method also adjust subviews position to create a tight wrap.
Adjust the view's width & height to wrap all its subviews that are included in the size calculation. The method also adjust subviews position to create a tight wrap.
*/
@discardableResult
public func wrapContent() -> PinLayout {
return wrapContent(.all, padding: PEdgeInsets(top: 0, left: 0, bottom: 0, right: 0), { return "wrapContent()" })
}

/**
Adjust the view's width & height to wrap all its subviews. The method also adds a padding around all subviews.
Adjust the view's width & height to wrap all its subviews that are included in the size calculation. The method also adds a padding around all subviews.

- Parameters:
- padding: Specify a padding value.
Expand All @@ -45,7 +45,7 @@ extension PinLayout {

/**
The method...
- Adjust the view's width and height to wrap all its subviews.
- Adjust the view's width and height to wrap all its subviews that are included in the size calculation.
- Adjust subviews's position to create a tight wrap.
- Apply padding around all subviews.

Expand All @@ -59,7 +59,7 @@ extension PinLayout {

/**
The method...
- Adjust the view's width and height to wrap all its subviews.
- Adjust the view's width and height to wrap all its subviews that are included in the size calculation.
- Adjust subviews's position to create a tight wrap.

- Parameters:
Expand All @@ -72,7 +72,7 @@ extension PinLayout {

/**
The method...
- Adjust the view's width and height to wrap all its subviews.
- Adjust the view's width and height to wrap all its subviews that are included in the size calculation.
- Adjust subviews's position to create a tight wrap.
- Apply padding around all subviews.

Expand All @@ -87,7 +87,7 @@ extension PinLayout {

/**
The method...
- Adjust the view's width and height to wrap all its subviews.
- Adjust the view's width and height to wrap all its subviews that are included in the size calculation.
- Adjust subviews's position to create a tight wrap.
- Apply padding around all subviews.

Expand All @@ -101,11 +101,11 @@ extension PinLayout {
}

private func wrapContent(_ type: WrapType, padding: PEdgeInsets, _ context: Context) -> PinLayout {
let subviews = view.subviews
guard !subviews.isEmpty else { return self }
let includedSubviews = view.subviewsIncludedInSizeCalculation
guard !includedSubviews.isEmpty else { return self }

let firstViewRect = subviews[0].getRect(keepTransform: keepTransform)
let boundingRect = subviews.reduce(firstViewRect, { (result, view) in
let firstViewRect = includedSubviews[0].getRect(keepTransform: keepTransform)
let boundingRect = includedSubviews.reduce(firstViewRect, { (result, view) in
result.union(view.getRect(keepTransform: keepTransform))
})

Expand All @@ -131,7 +131,7 @@ extension PinLayout {
}

if offsetDx != 0 || offsetDy != 0 {
subviews.forEach { (view) in
includedSubviews.forEach { (view) in
let viewRect = view.getRect(keepTransform: keepTransform)
let newRect = viewRect.offsetBy(dx: offsetDx, dy: offsetDy)
view.setRect(newRect, keepTransform: keepTransform)
Expand Down
6 changes: 3 additions & 3 deletions Sources/Types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,11 @@ public enum FitType {
}

@objc public enum WrapType: Int {
/// Adjust the view's width AND height to wrap all its subviews.
/// Adjust the view's width AND height to wrap all its subviews that are included in the size calculation.
case all
/// Adjust only the view's width to wrap all its subviews. The view's height won't be modified.
/// Adjust only the view's width to wrap all its subviews that are included in the size calculation. The view's height won't be modified.
case horizontally
/// Adjust only the view's height to wrap all its subviews. The view's width won't be modified.
/// Adjust only the view's height to wrap all its subviews that are included in the size calculation. The view's width won't be modified.
case vertically
}

Expand Down