Skip to content

Commit

Permalink
Inlining
Browse files Browse the repository at this point in the history
  • Loading branch information
tevelee committed Jun 27, 2024
1 parent aee5aa2 commit 3f6bd56
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 15 deletions.
29 changes: 25 additions & 4 deletions Sources/Flow/HFlow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ import SwiftUI
/// }
///
@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
@frozen
public struct HFlow<Content: View>: View {
private let layout: HFlowLayout
private let content: Content
@usableFromInline
let layout: HFlowLayout
@usableFromInline
let content: Content

/// Creates a horizontal flow with the given spacing and vertical alignment.
///
Expand All @@ -38,6 +41,7 @@ public struct HFlow<Content: View>: View {
/// mode tries to distribute items more evenly by minimizing the empty
/// spaces left in each row, while respecting their order.
/// - content: A view builder that creates the content of this flow.
@inlinable
public init(
alignment: VerticalAlignment = .center,
itemSpacing: CGFloat? = nil,
Expand Down Expand Up @@ -69,6 +73,7 @@ public struct HFlow<Content: View>: View {
/// mode tries to distribute items more evenly by minimizing the empty
/// spaces left in each row, while respecting their order.
/// - content: A view builder that creates the content of this flow.
@inlinable
public init(
alignment: VerticalAlignment = .center,
spacing: CGFloat? = nil,
Expand All @@ -86,6 +91,7 @@ public struct HFlow<Content: View>: View {
)
}

@inlinable
public var body: some View {
layout {
content
Expand Down Expand Up @@ -114,6 +120,7 @@ extension HFlow: Layout where Content == EmptyView {
/// - distributeItemsEvenly: Instead of prioritizing the first rows, this
/// mode tries to distribute items more evenly by minimizing the empty
/// spaces left in each row, while respecting their order.
@inlinable
public init(
alignment: VerticalAlignment = .center,
itemSpacing: CGFloat? = nil,
Expand Down Expand Up @@ -144,6 +151,7 @@ extension HFlow: Layout where Content == EmptyView {
/// - distributeItemsEvenly: Instead of prioritizing the first rows, this
/// mode tries to distribute items more evenly by minimizing the empty
/// spaces left in each row, while respecting their order.
@inlinable
public init(
alignment: VerticalAlignment = .center,
spacing: CGFloat? = nil,
Expand All @@ -160,15 +168,26 @@ extension HFlow: Layout where Content == EmptyView {
}
}

public func sizeThatFits(proposal: ProposedViewSize, subviews: LayoutSubviews, cache: inout FlowLayoutCache) -> CGSize {
@inlinable
public func sizeThatFits(
proposal: ProposedViewSize,
subviews: LayoutSubviews,
cache: inout FlowLayoutCache
) -> CGSize {
layout.sizeThatFits(
proposal: proposal,
subviews: subviews,
cache: &cache
)
}

public func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: LayoutSubviews, cache: inout FlowLayoutCache) {
@inlinable
public func placeSubviews(
in bounds: CGRect,
proposal: ProposedViewSize,
subviews: LayoutSubviews,
cache: inout FlowLayoutCache
) {
layout.placeSubviews(
in: bounds,
proposal: proposal,
Expand All @@ -177,10 +196,12 @@ extension HFlow: Layout where Content == EmptyView {
)
}

@inlinable
public func makeCache(subviews: LayoutSubviews) -> FlowLayoutCache {
FlowLayoutCache(subviews, axis: .horizontal)
}

@inlinable
public static var layoutProperties: LayoutProperties {
HFlowLayout.layoutProperties
}
Expand Down
9 changes: 8 additions & 1 deletion Sources/Flow/HFlowLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import SwiftUI

/// A layout that arranges its children in a horizontally flowing manner.
@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
@frozen
public struct HFlowLayout {
private let layout: FlowLayout
@usableFromInline
let layout: FlowLayout

/// Creates a horizontal flow with the given spacing and vertical alignment.
///
Expand All @@ -17,6 +19,7 @@ public struct HFlowLayout {
/// - distributeItemsEvenly: Instead of prioritizing the first rows, this
/// mode tries to distribute items more evenly by minimizing the empty
/// spaces left in each row, while respecting their order.
@inlinable
public init(
alignment: VerticalAlignment = .center,
itemSpacing: CGFloat? = nil,
Expand All @@ -36,18 +39,22 @@ public struct HFlowLayout {

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
extension HFlowLayout: Layout {
@inlinable
public func sizeThatFits(proposal: ProposedViewSize, subviews: LayoutSubviews, cache: inout FlowLayoutCache) -> CGSize {
layout.sizeThatFits(proposal: proposal, subviews: subviews, cache: &cache)
}

@inlinable
public func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: LayoutSubviews, cache: inout FlowLayoutCache) {
layout.placeSubviews(in: bounds, proposal: proposal, subviews: subviews, cache: &cache)
}

@inlinable
public func makeCache(subviews: LayoutSubviews) -> FlowLayoutCache {
FlowLayoutCache(subviews, axis: .horizontal)
}

@inlinable
public static var layoutProperties: LayoutProperties {
var properties = LayoutProperties()
properties.stackOrientation = .horizontal
Expand Down
9 changes: 8 additions & 1 deletion Sources/Flow/Internal/Layout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import CoreFoundation
import SwiftUI

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
@usableFromInline
struct FlowLayout {
let axis: Axis
var itemSpacing: CGFloat?
Expand All @@ -28,6 +29,7 @@ struct FlowLayout {
private typealias Line = [ItemWithSpacing<Item>]
private typealias Lines = [ItemWithSpacing<Line>]

@usableFromInline
func sizeThatFits(
proposal proposedSize: ProposedViewSize,
subviews: some Subviews,
Expand All @@ -44,6 +46,7 @@ struct FlowLayout {
return CGSize(size: size, axis: axis)
}

@usableFromInline
func placeSubviews(
in bounds: CGRect,
proposal: ProposedViewSize,
Expand Down Expand Up @@ -257,10 +260,12 @@ struct FlowLayout {

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
extension FlowLayout: Layout {
@usableFromInline
func makeCache(subviews: LayoutSubviews) -> FlowLayoutCache {
makeCache(subviews)
}

@usableFromInline
static func vertical(
alignment: HorizontalAlignment,
itemSpacing: CGFloat?,
Expand All @@ -279,6 +284,7 @@ extension FlowLayout: Layout {
}
}

@usableFromInline
static func horizontal(
alignment: VerticalAlignment,
itemSpacing: CGFloat?,
Expand All @@ -298,7 +304,8 @@ extension FlowLayout: Layout {
}
}

private extension Array where Element == Size {
extension Array where Element == Size {
@inlinable
func reduce(
_ initial: Size,
breadth: (CGFloat, CGFloat) -> CGFloat,
Expand Down
4 changes: 3 additions & 1 deletion Sources/Flow/Internal/LineBreaking.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import CoreFoundation

@inlinable
func knuthPlassLineBreakingAlgorithm(
proposedBreadth: CGFloat,
sizes: [Size],
Expand All @@ -21,7 +22,8 @@ func knuthPlassLineBreakingAlgorithm(
return breakpoints
}

private func calculateOptimalBreaks(
@usableFromInline
func calculateOptimalBreaks(
proposedBreadth: CGFloat,
sizes: [Size],
spacings: [CGFloat]
Expand Down
6 changes: 6 additions & 0 deletions Sources/Flow/Internal/Protocols.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import SwiftUI

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
@usableFromInline
protocol Subviews: RandomAccessCollection where Element: Subview, Index == Int {}

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
extension LayoutSubviews: Subviews {}

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
@usableFromInline
protocol Subview {
var spacing: ViewSpacing { get }
var priority: Double { get }
Expand All @@ -17,11 +19,13 @@ protocol Subview {

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
extension LayoutSubview: Subview {
@usableFromInline
func dimensions(_ proposal: ProposedViewSize) -> Dimensions {
dimensions(in: proposal)
}
}

@usableFromInline
protocol Dimensions {
var width: CGFloat { get }
var height: CGFloat { get }
Expand All @@ -32,13 +36,15 @@ protocol Dimensions {
extension ViewDimensions: Dimensions {}

extension Dimensions {
@usableFromInline
func size(on axis: Axis) -> Size {
Size(
breadth: value(on: axis),
depth: value(on: axis.perpendicular)
)
}

@usableFromInline
func value(on axis: Axis) -> CGFloat {
switch axis {
case .horizontal: width
Expand Down
22 changes: 21 additions & 1 deletion Sources/Flow/Internal/Size.swift
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
import CoreFoundation
import SwiftUI

@usableFromInline
struct Size {
@usableFromInline
var breadth: CGFloat
@usableFromInline
var depth: CGFloat

@usableFromInline
init(breadth: CGFloat, depth: CGFloat) {
self.breadth = breadth
self.depth = depth
}

@usableFromInline
static let zero = Size(breadth: 0, depth: 0)

@usableFromInline
func adding(_ value: CGFloat, on axis: Axis) -> Size {
var size = self
size[axis] += value
return size
}

fileprivate subscript(axis: Axis) -> CGFloat {
@usableFromInline
subscript(axis: Axis) -> CGFloat {
get {
self[keyPath: keyPath(on: axis)]
}
Expand All @@ -31,6 +43,7 @@ struct Size {
}

extension Axis {
@usableFromInline
var perpendicular: Axis {
switch self {
case .horizontal: .vertical
Expand All @@ -47,16 +60,19 @@ protocol FixedOrientation2DCoordinate {
}

extension FixedOrientation2DCoordinate {
@inlinable
func size(on axis: Axis) -> Size {
Size(breadth: value(on: axis), depth: value(on: axis.perpendicular))
}
}

extension CGPoint: FixedOrientation2DCoordinate {
@inlinable
init(size: Size, axis: Axis) {
self.init(x: size[axis], y: size[axis.perpendicular])
}

@inlinable
func value(on axis: Axis) -> CGFloat {
switch axis {
case .horizontal: x
Expand All @@ -66,10 +82,12 @@ extension CGPoint: FixedOrientation2DCoordinate {
}

extension CGSize: FixedOrientation2DCoordinate {
@inlinable
init(size: Size, axis: Axis) {
self.init(width: size[axis], height: size[axis.perpendicular])
}

@inlinable
func value(on axis: Axis) -> CGFloat {
switch axis {
case .horizontal: width
Expand All @@ -80,10 +98,12 @@ extension CGSize: FixedOrientation2DCoordinate {

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
extension ProposedViewSize: FixedOrientation2DCoordinate {
@inlinable
init(size: Size, axis: Axis) {
self.init(width: size[axis], height: size[axis.perpendicular])
}

@inlinable
func value(on axis: Axis) -> CGFloat {
switch axis {
case .horizontal: width ?? .infinity
Expand Down
2 changes: 2 additions & 0 deletions Sources/Flow/Internal/Utils.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
extension Sequence {
@inlinable
func adjacentPairs() -> some Sequence<(Element, Element)> {
zip(self, self.dropFirst())
}

@inlinable
func sum<Result: Numeric>(of block: (Element) -> Result) -> Result {
reduce(into: .zero) { $0 += block($1) }
}
Expand Down
4 changes: 4 additions & 0 deletions Sources/Flow/Support.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ public enum Justification {
/// it's considered an internal implementation detail.
@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
public struct FlowLayoutCache {
@usableFromInline
struct SubviewCache {
var priority: Double
var spacing: ViewSpacing
var min: Size
var ideal: Size
var max: Size

@usableFromInline
init(_ subview: some Subview, axis: Axis) {
priority = subview.priority
spacing = subview.spacing
Expand All @@ -46,8 +48,10 @@ public struct FlowLayoutCache {
}
}

@usableFromInline
let subviewsCache: [SubviewCache]

@inlinable
init(_ subviews: some Subviews, axis: Axis) {
subviewsCache = subviews.map {
SubviewCache($0, axis: axis)
Expand Down
Loading

0 comments on commit 3f6bd56

Please sign in to comment.