diff --git a/README.md b/README.md index 47045d2..df3b389 100644 --- a/README.md +++ b/README.md @@ -1371,20 +1371,24 @@ The following methods are useful to adjust view's width and/or height to wrap al **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. -* **`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. - +* **`wrapContent(viewFilter: ViewFilter = .all)`** +**`wrapContent(padding: CGFloat, viewFilter: ViewFilter = .all)`** +**`wrapContent(padding: UIEdgeInsets, viewFilter: ViewFilter = .all)`** +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. Additionally, it's possible to specify whether to include all views or only visible ones. +* **`wrapContent(:WrapType, viewFilter: ViewFilter = .all)`** **`wrapContent(:WrapType, padding: UIEdgeInsets, viewFilter: ViewFilter = .all)`** +**`wrapContent(:WrapType, padding: CGFloat, viewFilter: ViewFilter = .all)`** +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. Additionally, it's possible to specify whether to include all views or only visible ones. + **Types:** * **`WrapType`** values: * `.horizontally`: Adjust the view's width and update subviews's horizontal position. * `.vertically`: Adjust only the view's height and update subviews's vertical position. * `.all`: Adjust the view's width AND height and update subviews position. This is the default WrapType parameter value `wrapContent()` methods. + +* **`ViewFilter`** values: + * `.all`: Consider all views + * `.visibleOnly`: Consider only visible views (isHidden is false and alpha is > 0) ###### Usage examples: ```swift @@ -1957,3 +1961,4 @@ PinLayout recent history is available in the [CHANGELOG](CHANGELOG.md) also in [ ## License MIT License + diff --git a/Sources/Extensions/CALayer+PinLayout.swift b/Sources/Extensions/CALayer+PinLayout.swift index 7eb92be..3d9e64a 100644 --- a/Sources/Extensions/CALayer+PinLayout.swift +++ b/Sources/Extensions/CALayer+PinLayout.swift @@ -30,6 +30,10 @@ extension CALayer: Layoutable { return sublayers ?? [] } + public var isConsideredVisibleForViewFilters: Bool { + return !isHidden && opacity > 0 + } + public var pin: PinLayout { return PinLayout(view: self, keepTransform: true) } diff --git a/Sources/Extensions/NSView+PinLayout.swift b/Sources/Extensions/NSView+PinLayout.swift index ee81f9a..fb966d4 100644 --- a/Sources/Extensions/NSView+PinLayout.swift +++ b/Sources/Extensions/NSView+PinLayout.swift @@ -33,6 +33,10 @@ extension NSView: Layoutable { return PinLayout(view: self, keepTransform: false) } + public var isConsideredVisibleForViewFilters: Bool { + return !isHidden && alphaValue > 0 + } + @objc public var pinObjc: PinLayoutObjC { return PinLayoutObjCImpl(view: self, keepTransform: true) } diff --git a/Sources/Extensions/UIView+PinLayout.swift b/Sources/Extensions/UIView+PinLayout.swift index 1a9c144..a1bb5f1 100644 --- a/Sources/Extensions/UIView+PinLayout.swift +++ b/Sources/Extensions/UIView+PinLayout.swift @@ -37,6 +37,10 @@ extension UIView: Layoutable, SizeCalculable { return PinLayoutObjCImpl(view: self, keepTransform: true) } + public var isConsideredVisibleForViewFilters: Bool { + return !isHidden && alpha > 0 + } + public func getRect(keepTransform: Bool) -> CGRect { guard !Pin.autoSizingInProgress || autoSizingRect == nil else { return autoSizingRect ?? CGRect.zero } diff --git a/Sources/Layoutable.swift b/Sources/Layoutable.swift index fa4e996..8ed5a31 100644 --- a/Sources/Layoutable.swift +++ b/Sources/Layoutable.swift @@ -29,6 +29,8 @@ public protocol Layoutable: AnyObject, Equatable, CustomDebugStringConvertible { var superview: PinView? { get } var subviews: [PinView] { get } + var isConsideredVisibleForViewFilters: Bool { get } + func getRect(keepTransform: Bool) -> CGRect func setRect(_ rect: CGRect, keepTransform: Bool) diff --git a/Sources/PinLayout+WrapContent.swift b/Sources/PinLayout+WrapContent.swift index e58731c..c2b1621 100644 --- a/Sources/PinLayout+WrapContent.swift +++ b/Sources/PinLayout+WrapContent.swift @@ -26,10 +26,13 @@ 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. + + - Parameters: + - viewFilter: Specify whether to include all views or only visible ones. */ @discardableResult - public func wrapContent() -> PinLayout { - return wrapContent(.all, padding: PEdgeInsets(top: 0, left: 0, bottom: 0, right: 0), { return "wrapContent()" }) + public func wrapContent(viewFilter: ViewFilter = .all) -> PinLayout { + return wrapContent(.all, padding: PEdgeInsets(top: 0, left: 0, bottom: 0, right: 0), viewFilter: viewFilter, { return "wrapContent()" }) } /** @@ -37,10 +40,11 @@ extension PinLayout { - Parameters: - padding: Specify a padding value. + - viewFilter: Specify whether to include all views or only visible ones. */ @discardableResult - public func wrapContent(padding: CGFloat) -> PinLayout { - return wrapContent(.all, padding: PEdgeInsets(top: padding, left: padding, bottom: padding, right: padding), { return "wrapContent(padding: \(padding)" }) + public func wrapContent(padding: CGFloat, viewFilter: ViewFilter = .all) -> PinLayout { + return wrapContent(.all, padding: PEdgeInsets(top: padding, left: padding, bottom: padding, right: padding), viewFilter: viewFilter, { return "wrapContent(padding: \(padding)" }) } /** @@ -51,10 +55,11 @@ extension PinLayout { - Parameters: - padding: Specify a padding using an UIEdgeInsets. + - viewFilter: Specify whether to include all views or only visible ones. */ @discardableResult - public func wrapContent(padding: PEdgeInsets) -> PinLayout { - return wrapContent(.all, padding: padding, { return "wrapContent(padding: \(insetsDescription(padding))" }) + public func wrapContent(padding: PEdgeInsets, viewFilter: ViewFilter = .all) -> PinLayout { + return wrapContent(.all, padding: padding, viewFilter: viewFilter, { return "wrapContent(padding: \(insetsDescription(padding))" }) } /** @@ -64,10 +69,11 @@ extension PinLayout { - Parameters: - type: Specify the wrap type (.all, .horizontally, .vertically) + - viewFilter: Specify whether to include all views or only visible ones. */ @discardableResult - public func wrapContent(_ type: WrapType) -> PinLayout { - return wrapContent(type, padding: PEdgeInsets(top: 0, left: 0, bottom: 0, right: 0), { return "wrapContent(\(type.description)" }) + public func wrapContent(_ type: WrapType, viewFilter: ViewFilter = .all) -> PinLayout { + return wrapContent(type, padding: PEdgeInsets(top: 0, left: 0, bottom: 0, right: 0), viewFilter: viewFilter, { return "wrapContent(\(type.description)" }) } /** @@ -79,10 +85,11 @@ extension PinLayout { - Parameters: - type: Specify the wrap type (.all, .horizontally, .vertically) - padding: Specify a padding value. + - viewFilter: Specify whether to include all views or only visible ones. */ @discardableResult - public func wrapContent(_ type: WrapType, padding: CGFloat) -> PinLayout { - return wrapContent(type, padding: PEdgeInsets(top: padding, left: padding, bottom: padding, right: padding), { return "wrapContent(\(type.description), padding: \(padding)" }) + public func wrapContent(_ type: WrapType, padding: CGFloat, viewFilter: ViewFilter = .all) -> PinLayout { + return wrapContent(type, padding: PEdgeInsets(top: padding, left: padding, bottom: padding, right: padding), viewFilter: viewFilter, { return "wrapContent(\(type.description), padding: \(padding)" }) } /** @@ -94,14 +101,22 @@ extension PinLayout { - Parameters: - type: Specify the wrap type (.all, .horizontally, .vertically) - padding: Specify a padding using an UIEdgeInsets. + - viewFilter: Specify whether to include all views or only visible ones. */ @discardableResult - public func wrapContent(_ type: WrapType, padding: PEdgeInsets) -> PinLayout { - return wrapContent(type, padding: padding, { return "wrapContent(\(type.description), padding: \(insetsDescription(padding))" }) + public func wrapContent(_ type: WrapType, padding: PEdgeInsets, viewFilter: ViewFilter = .all) -> PinLayout { + return wrapContent(type, padding: padding, viewFilter: viewFilter, { return "wrapContent(\(type.description), padding: \(insetsDescription(padding))" }) } - private func wrapContent(_ type: WrapType, padding: PEdgeInsets, _ context: Context) -> PinLayout { - let subviews = view.subviews + private func wrapContent(_ type: WrapType, padding: PEdgeInsets, viewFilter: ViewFilter, _ context: Context) -> PinLayout { + let subviews: [PinView.PinView] + switch viewFilter { + case .visibleOnly: + subviews = view.subviews.filter { $0.isConsideredVisibleForViewFilters } + case .all: + subviews = view.subviews + } + guard !subviews.isEmpty else { return self } let firstViewRect = subviews[0].getRect(keepTransform: keepTransform) diff --git a/Sources/Types.swift b/Sources/Types.swift index 90ab6bb..2313456 100644 --- a/Sources/Types.swift +++ b/Sources/Types.swift @@ -194,6 +194,13 @@ public enum FitType { case vertically } +@objc public enum ViewFilter: Int { + /// Consider all views + case all + /// Consider only visible views (isHidden is false and alpha is > 0) + case visibleOnly +} + @objc public enum LayoutDirection: Int { case auto case ltr