Skip to content

Commit

Permalink
Fix VisibleBoundsObserverRenderNode
Browse files Browse the repository at this point in the history
  • Loading branch information
lkzhao committed May 13, 2024
1 parent 15cad0b commit 2657e06
Show file tree
Hide file tree
Showing 8 changed files with 22 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public struct DynamicHPager: Component {
/// - count: The total number of pages.
/// - alignItems: Defines how child components are aligned along the cross axis.
/// - content: A closure that provides the content for a given page index.
public init(count: Int, alignItems: CrossAxisAlignment, content: @escaping (Int) -> any Component) {
public init(count: Int, alignItems: CrossAxisAlignment = .start, content: @escaping (Int) -> any Component) {
self.count = count
self.alignItems = alignItems
self.content = content
Expand Down Expand Up @@ -52,7 +52,7 @@ public struct DynamicVPager: Component {
/// - count: The total number of pages.
/// - alignItems: Defines how child components are aligned along the cross axis.
/// - content: A closure that provides the content for a given page index.
public init(count: Int, alignItems: CrossAxisAlignment, content: @escaping (Int) -> any Component) {
public init(count: Int, alignItems: CrossAxisAlignment = .start, content: @escaping (Int) -> any Component) {
self.count = count
self.alignItems = alignItems
self.content = content
Expand Down
4 changes: 0 additions & 4 deletions Sources/UIComponent/Components/Layout/Other/Offset.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,4 @@ struct OffsetRenderNode: RenderNode {
var positions: [CGPoint] {
[offset]
}

func visibleIndexes(in frame: CGRect) -> any Collection<Int> {
[0]
}
}
21 changes: 12 additions & 9 deletions Sources/UIComponent/Components/Layout/Stack/StackRenderNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import UIKit

/// A base render node protocol for a stack that provide implementation for ``visibleIndexes(in:)``
/// A base render node protocol for a stack that provide implementation for ``visibleChildren(in:)``
public protocol StackRenderNode: RenderNode, BaseLayoutProtocol {
/// The size of the render node.
var size: CGSize { get }
Expand All @@ -16,14 +16,16 @@ public protocol StackRenderNode: RenderNode, BaseLayoutProtocol {
}

extension StackRenderNode {
public func visibleIndexes(in frame: CGRect) -> any Collection<Int> {
public func visibleChildren(in frame: CGRect) -> [RenderNodeChild] {
guard let start = firstVisibleIndex(in: frame) else { return [] }
var index = start
let endPoint = main(frame.origin) + main(frame.size)
while index < positions.count, main(positions[index]) < endPoint {
index += 1
}
return IndexSet(start..<index)
return (start..<index).map {
RenderNodeChild(renderNode: children[$0], position: positions[$0], index: $0)
}
}

public func firstVisibleIndex(in frame: CGRect) -> Int? {
Expand Down Expand Up @@ -96,18 +98,19 @@ public struct SlowRenderNode: RenderNode {
self.positions = positions
}

public func visibleIndexes(in frame: CGRect) -> any Collection<Int> {
var result = [Int]()
public func visibleChildren(in frame: CGRect) -> [RenderNodeChild] {
var result = [RenderNodeChild]()

for (i, origin) in positions.enumerated() {
for (i, position) in positions.enumerated() {
let child = children[i]
let childFrame = CGRect(origin: origin, size: child.size)
let childFrame = CGRect(origin: position, size: child.size)
if frame.intersects(childFrame) {
result.append(i)
let nodeChild = RenderNodeChild(renderNode: child, position: position, index: i)
result.append(nodeChild)
}
}

return IndexSet(result)
return result
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ public struct VisibleBoundsObserverRenderNode<Content: RenderNode>: RenderNodeWr
self.onVisibleBoundsChanged = onVisibleBoundsChanged
}

public func visibleIndexes(in frame: CGRect) -> any Collection<Int> {
public func visibleChildren(in frame: CGRect) -> [RenderNodeChild] {
onVisibleBoundsChanged(size, frame)
return content.visibleIndexes(in: frame)
return content.visibleChildren(in: frame)
}
}
6 changes: 0 additions & 6 deletions Sources/UIComponent/Core/Model/RenderNode/AnyRenderNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ public struct AnyRenderNode: RenderNode {
public var shouldRenderView: Bool {
erasing.shouldRenderView
}
public func visibleIndexes(in frame: CGRect) -> any Collection<Int> {
erasing.visibleIndexes(in: frame)
}
public func visibleChildren(in frame: CGRect) -> [RenderNodeChild] {
erasing.visibleChildren(in: frame)
}
Expand Down Expand Up @@ -95,9 +92,6 @@ public struct AnyRenderNodeOfView<View: UIView>: RenderNode {
public var shouldRenderView: Bool {
erasing.shouldRenderView
}
public func visibleIndexes(in frame: CGRect) -> any Collection<Int> {
erasing.visibleIndexes(in: frame)
}
public func visibleChildren(in frame: CGRect) -> [RenderNodeChild] {
erasing.visibleChildren(in: frame)
}
Expand Down
25 changes: 5 additions & 20 deletions Sources/UIComponent/Core/Model/RenderNode/RenderNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,36 +33,25 @@ public protocol RenderNode<View> {
/// The child render nodes of this node.
var children: [any RenderNode] { get }

/// Returns the indexes of the children that are visible within the given frame.
///
/// - Parameter frame: The frame within which to determine visibility of children.
/// - Returns: The indexes of the children that are visible within the given frame.
///
/// This method is used in the default implementation of `visibleRenderables(in:)`.
/// It won't be called if `visibleRenderables(in:)` is overwritten.
/// The default implementation for this methods is not optmized and will return all indexes regardless of the frame.
func visibleIndexes(in frame: CGRect) -> any Collection<Int>

/// Returns the render nodes that are visible within the given frame.
///
/// - Parameter frame: The frame within which to determine visibility of renderables.
/// - Returns: The render nodes that are visible within the given frame. The objects to return are `RenderNodeChild` which contains
/// the child render node, the position relative to the parent, and the index of the child (for structure identity only, not used to access `children` or `positions`).
///
/// The default implementation calls ``RenderNode/visibleIndexes(in:)-1jtpe`` to get the visible childrens. And return the corresponding RenderNodeChild by combining data from `children` and `positions`.
/// The default implementation return all children. And return the corresponding RenderNodeChild by combining data from `children` and `positions`.
func visibleChildren(in frame: CGRect) -> [RenderNodeChild]

/// Method called before `visibleChildren(in:)` to adjust the visible frame.
func adjustVisibleFrame(frame: CGRect) -> CGRect

/// Creates a new view instance for this render node.
func makeView() -> View

/// Updates the provided view with the current state of this render node.
///
/// - Parameter view: The view to update.
func updateView(_ view: View)


/// Method called before `visibleChildren(in:)` to adjust the visible frame.
func adjustVisibleFrame(frame: CGRect) -> CGRect
}

// MARK: - Helper methods
Expand Down Expand Up @@ -129,12 +118,8 @@ extension RenderNode {
public var children: [any RenderNode] { [] }
public var positions: [CGPoint] { [] }

public func visibleIndexes(in frame: CGRect) -> any Collection<Int> {
IndexSet(0..<children.count)
}

public func visibleChildren(in frame: CGRect) -> [RenderNodeChild] {
visibleIndexes(in: frame).map {
(0..<children.count).map {
RenderNodeChild(renderNode: children[$0], position: positions[$0], index: $0)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ extension RenderNodeWrapper {
public var shouldRenderView: Bool {
content.shouldRenderView
}
public func visibleIndexes(in frame: CGRect) -> any Collection<Int> {
content.visibleIndexes(in: frame)
}
public func visibleChildren(in frame: CGRect) -> [RenderNodeChild] {
content.visibleChildren(in: frame)
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/UIComponent/Documentation.docc/RenderNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ To create a custom ``RenderNode``, you need to write a struct that conforms to `
- ``RenderNode/size``
- ``RenderNode/positions-6f59e``
- ``RenderNode/children-42h1l``
- ``RenderNode/visibleIndexes(in:)-65qgr``
- ``RenderNode/visibleChildren(in:)-4nvhh``
- ``RenderNode/shouldRenderView(in:)-yvrd``
- ``RenderNode/makeView()-8w5z2``
- ``RenderNode/updateView(_:)-2xjz4``
Expand Down

0 comments on commit 2657e06

Please sign in to comment.