From f5fa69e0bc798f373fe7a812e811f8cb314e6755 Mon Sep 17 00:00:00 2001 From: Casper Zandbergen Date: Wed, 28 Nov 2018 11:04:40 +0100 Subject: [PATCH 1/7] `visibleIndexes(visibleFrame:)` is now `visible(for:)` and returns both the visible indexes and the frame they appear in. This frame can be different from the input frame if the layout changes it (like VisibleFrameInsetLayout does). --- CollectionKitTests/FlowLayoutSpec.swift | 2 +- CollectionKitTests/WaterfallLayoutSpec.swift | 2 +- Sources/CollectionView.swift | 2 +- Sources/Layout/InsetLayout.swift | 4 +- Sources/Layout/Layout.swift | 2 +- Sources/Layout/SimpleLayout.swift | 12 +++--- Sources/Layout/StickyLayout.swift | 14 ++++--- Sources/Layout/TransposeLayout.swift | 4 +- Sources/Layout/VisibleFrameInsetLayout.swift | 4 +- Sources/Layout/WrapperLayout.swift | 4 +- Sources/Protocol/LayoutableProvider.swift | 4 +- Sources/Protocol/Provider.swift | 2 +- .../Provider/EmptyCollectionProvider.swift | 4 +- Sources/Provider/FlattenedProvider.swift | 37 +++++++++++-------- 14 files changed, 53 insertions(+), 44 deletions(-) diff --git a/CollectionKitTests/FlowLayoutSpec.swift b/CollectionKitTests/FlowLayoutSpec.swift index ba52eac..b910261 100644 --- a/CollectionKitTests/FlowLayoutSpec.swift +++ b/CollectionKitTests/FlowLayoutSpec.swift @@ -49,7 +49,7 @@ class FlowLayoutSpec: QuickSpec { it("should not display cells outside of the visible area") { let layout = FlowLayout().transposed() layout.mockLayout(parentSize: (100, 50), (50, 50), (50, 50), (50, 50), (50, 50)) - let visible = layout.visibleIndexes(visibleFrame: CGRect(x: 50, y: 0, width: 100, height: 50)) + let visible = layout.visible(for: CGRect(x: 50, y: 0, width: 100, height: 50)).indexes expect(visible).to(equal([1, 2])) } } diff --git a/CollectionKitTests/WaterfallLayoutSpec.swift b/CollectionKitTests/WaterfallLayoutSpec.swift index 62c409e..01207fc 100644 --- a/CollectionKitTests/WaterfallLayoutSpec.swift +++ b/CollectionKitTests/WaterfallLayoutSpec.swift @@ -46,7 +46,7 @@ class WaterfallLayoutSpec: QuickSpec { it("should not display cells outside of the visible area") { let layout = WaterfallLayout() layout.mockLayout(parentSize: (100, 50), (50, 50), (50, 50), (50, 50), (50, 50)) - let visible = layout.visibleIndexes(visibleFrame: CGRect(x: 0, y: 50, width: 100, height: 50)) + let visible = layout.visible(for: CGRect(x: 0, y: 50, width: 100, height: 50)).indexes expect(visible).to(equal([2, 3])) } } diff --git a/Sources/CollectionView.swift b/Sources/CollectionView.swift index dbe0fbe..1f93ccb 100644 --- a/Sources/CollectionView.swift +++ b/Sources/CollectionView.swift @@ -158,7 +158,7 @@ open class CollectionView: UIScrollView { } private func _loadCells(forceReload: Bool) { - let newIndexes = flattenedProvider.visibleIndexes(visibleFrame: visibleFrame) + let newIndexes = flattenedProvider.visible(for: visibleFrame).indexes // optimization: we assume that corresponding identifier for each index doesnt change unless forceReload is true. guard forceReload || diff --git a/Sources/Layout/InsetLayout.swift b/Sources/Layout/InsetLayout.swift index 71f21df..e701221 100644 --- a/Sources/Layout/InsetLayout.swift +++ b/Sources/Layout/InsetLayout.swift @@ -55,8 +55,8 @@ open class InsetLayout: WrapperLayout { rootLayout.layout(context: InsetLayoutContext(original: context, insets: insets)) } - open override func visibleIndexes(visibleFrame: CGRect) -> [Int] { - return rootLayout.visibleIndexes(visibleFrame: visibleFrame.inset(by: -insets)) + open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + return rootLayout.visible(for: visibleFrame.inset(by: -insets)) } open override func frame(at: Int) -> CGRect { diff --git a/Sources/Layout/Layout.swift b/Sources/Layout/Layout.swift index 7211c7a..de511c1 100644 --- a/Sources/Layout/Layout.swift +++ b/Sources/Layout/Layout.swift @@ -22,7 +22,7 @@ open class Layout { fatalError("Subclass should provide its own layout") } - open func visibleIndexes(visibleFrame: CGRect) -> [Int] { + open func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { fatalError("Subclass should provide its own layout") } diff --git a/Sources/Layout/SimpleLayout.swift b/Sources/Layout/SimpleLayout.swift index bba9152..148b303 100644 --- a/Sources/Layout/SimpleLayout.swift +++ b/Sources/Layout/SimpleLayout.swift @@ -36,14 +36,14 @@ open class SimpleLayout: Layout { return frames[at] } - open override func visibleIndexes(visibleFrame: CGRect) -> [Int] { + open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { var result = [Int]() for (i, frame) in frames.enumerated() { if frame.intersects(visibleFrame) { result.append(i) } } - return result + return (result, visibleFrame) } } @@ -54,7 +54,7 @@ open class VerticalSimpleLayout: SimpleLayout { maxFrameLength = frames.max { $0.height < $1.height }?.height ?? 0 } - open override func visibleIndexes(visibleFrame: CGRect) -> [Int] { + open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { var index = frames.binarySearch { $0.minY < visibleFrame.minY - maxFrameLength } var visibleIndexes = [Int]() while index < frames.count { @@ -67,7 +67,7 @@ open class VerticalSimpleLayout: SimpleLayout { } index += 1 } - return visibleIndexes + return (visibleIndexes, visibleFrame) } } @@ -78,7 +78,7 @@ open class HorizontalSimpleLayout: SimpleLayout { maxFrameLength = frames.max { $0.width < $1.width }?.width ?? 0 } - open override func visibleIndexes(visibleFrame: CGRect) -> [Int] { + open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { var index = frames.binarySearch { $0.minX < visibleFrame.minX - maxFrameLength } var visibleIndexes = [Int]() while index < frames.count { @@ -91,6 +91,6 @@ open class HorizontalSimpleLayout: SimpleLayout { } index += 1 } - return visibleIndexes + return (visibleIndexes, visibleFrame) } } diff --git a/Sources/Layout/StickyLayout.swift b/Sources/Layout/StickyLayout.swift index 8f86cb2..d8d26ff 100644 --- a/Sources/Layout/StickyLayout.swift +++ b/Sources/Layout/StickyLayout.swift @@ -34,17 +34,19 @@ public class StickyLayout: WrapperLayout { } } - public override func visibleIndexes(visibleFrame: CGRect) -> [Int] { + // TODO: Fix for the new FlattenedProvider.visible(for:) + public override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { self.visibleFrame = visibleFrame topFrameIndex = stickyFrames.binarySearch { $0.frame.minY < visibleFrame.minY } - 1 if let index = stickyFrames.get(topFrameIndex)?.index, index >= 0 { - var oldVisible = rootLayout.visibleIndexes(visibleFrame: visibleFrame) - if let index = oldVisible.index(of: index) { - oldVisible.remove(at: index) + var oldVisible = rootLayout.visible(for: visibleFrame) + if let index = oldVisible.indexes.index(of: index) { + oldVisible.indexes.remove(at: index) } - return oldVisible + [index] + oldVisible.indexes += [index] + return oldVisible } - return rootLayout.visibleIndexes(visibleFrame: visibleFrame) + return rootLayout.visible(for: visibleFrame) } public override func frame(at: Int) -> CGRect { diff --git a/Sources/Layout/TransposeLayout.swift b/Sources/Layout/TransposeLayout.swift index 59bcf07..f2f9f62 100644 --- a/Sources/Layout/TransposeLayout.swift +++ b/Sources/Layout/TransposeLayout.swift @@ -37,8 +37,8 @@ open class TransposeLayout: WrapperLayout { rootLayout.layout(context: TransposeLayoutContext(original: context)) } - open override func visibleIndexes(visibleFrame: CGRect) -> [Int] { - return rootLayout.visibleIndexes(visibleFrame: visibleFrame.transposed) + open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + return rootLayout.visible(for: visibleFrame.transposed) } open override func frame(at: Int) -> CGRect { diff --git a/Sources/Layout/VisibleFrameInsetLayout.swift b/Sources/Layout/VisibleFrameInsetLayout.swift index cafd98c..576e7e8 100644 --- a/Sources/Layout/VisibleFrameInsetLayout.swift +++ b/Sources/Layout/VisibleFrameInsetLayout.swift @@ -30,7 +30,7 @@ open class VisibleFrameInsetLayout: WrapperLayout { super.layout(context: context) } - open override func visibleIndexes(visibleFrame: CGRect) -> [Int] { - return rootLayout.visibleIndexes(visibleFrame: visibleFrame.inset(by: insets)) + open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + return rootLayout.visible(for: visibleFrame.inset(by: insets)) } } diff --git a/Sources/Layout/WrapperLayout.swift b/Sources/Layout/WrapperLayout.swift index 1163058..04cf7c6 100644 --- a/Sources/Layout/WrapperLayout.swift +++ b/Sources/Layout/WrapperLayout.swift @@ -23,8 +23,8 @@ open class WrapperLayout: Layout { rootLayout.layout(context: context) } - open override func visibleIndexes(visibleFrame: CGRect) -> [Int] { - return rootLayout.visibleIndexes(visibleFrame: visibleFrame) + open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + return rootLayout.visible(for: visibleFrame) } open override func frame(at: Int) -> CGRect { diff --git a/Sources/Protocol/LayoutableProvider.swift b/Sources/Protocol/LayoutableProvider.swift index e57ca19..df683ff 100644 --- a/Sources/Protocol/LayoutableProvider.swift +++ b/Sources/Protocol/LayoutableProvider.swift @@ -21,8 +21,8 @@ extension LayoutableProvider where Self: Provider { public func layout(collectionSize: CGSize) { internalLayout.layout(context: layoutContext(collectionSize: collectionSize)) } - public func visibleIndexes(visibleFrame: CGRect) -> [Int] { - return internalLayout.visibleIndexes(visibleFrame: visibleFrame) + public func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + return internalLayout.visible(for: visibleFrame) } public var contentSize: CGSize { return internalLayout.contentSize diff --git a/Sources/Protocol/Provider.swift b/Sources/Protocol/Provider.swift index eefd073..8578842 100644 --- a/Sources/Protocol/Provider.swift +++ b/Sources/Protocol/Provider.swift @@ -17,7 +17,7 @@ public protocol Provider { // layout func layout(collectionSize: CGSize) - func visibleIndexes(visibleFrame: CGRect) -> [Int] + func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) var contentSize: CGSize { get } func frame(at: Int) -> CGRect diff --git a/Sources/Provider/EmptyCollectionProvider.swift b/Sources/Provider/EmptyCollectionProvider.swift index 9554bfb..3147661 100644 --- a/Sources/Provider/EmptyCollectionProvider.swift +++ b/Sources/Provider/EmptyCollectionProvider.swift @@ -33,8 +33,8 @@ open class EmptyCollectionProvider: ItemProvider, CollectionReloadable { open func frame(at: Int) -> CGRect { return .zero } - open func visibleIndexes(visibleFrame: CGRect) -> [Int] { - return [Int]() + open func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + return ([Int](), visibleFrame) } open func animator(at: Int) -> Animator? { diff --git a/Sources/Provider/FlattenedProvider.swift b/Sources/Provider/FlattenedProvider.swift index a5d36f4..5466816 100644 --- a/Sources/Provider/FlattenedProvider.swift +++ b/Sources/Provider/FlattenedProvider.swift @@ -84,23 +84,26 @@ struct FlattenedProvider: ItemProvider { return provider.contentSize } - func visibleIndexes(visibleFrame: CGRect) -> [Int] { - var visible = [Int]() - for sectionIndex in provider.visibleIndexes(visibleFrame: visibleFrame) { - let beginIndex = childSections[sectionIndex].beginIndex - if let sectionData = childSections[sectionIndex].sectionData { - let sectionFrame = provider.frame(at: sectionIndex) - let intersectFrame = visibleFrame.intersection(sectionFrame) - let visibleFrameForCell = CGRect(origin: intersectFrame.origin - sectionFrame.origin, size: intersectFrame.size) - let sectionVisible = sectionData.visibleIndexes(visibleFrame: visibleFrameForCell) - for item in sectionVisible { - visible.append(item + beginIndex) - } - } else { - visible.append(beginIndex) + // BREAKS STICKY HEADERS + func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + let visibleFrame = provider.visible(for: visibleFrame).frame + + let indexes: [Int] = childSections.enumerated().flatMap { index, child -> [Int] in + let sectionFrame = provider.frame(at: index) + let intersectFrame = visibleFrame.intersection(sectionFrame) + var visibleFrameForCell = CGRect(origin: intersectFrame.origin - sectionFrame.origin, size: intersectFrame.size) + if intersectFrame.origin == .infinity { + // even if there is no intersection now, there might be + // after the layout adds visible frame inset so we still + // call the section with a valid frame + visibleFrameForCell.origin = visibleFrame.origin } + let visible = child.sectionData?.visible(for: visibleFrameForCell) + let indexes = visible?.indexes ?? [0] + return indexes.map { $0 + child.beginIndex } } - return visible + + return (indexes, visibleFrame) } func frame(at: Int) -> CGRect { @@ -138,3 +141,7 @@ struct FlattenedProvider: ItemProvider { return provider.hasReloadable(reloadable) } } + +extension CGPoint { + static var infinity: CGPoint = CGPoint(x: CGFloat.infinity, y: CGFloat.infinity) +} From 189f0877c279779f679fc61a5818693027a4e0c8 Mon Sep 17 00:00:00 2001 From: Casper Zandbergen Date: Wed, 28 Nov 2018 13:53:02 +0100 Subject: [PATCH 2/7] Fixed the bug where headers were not shown on top. The issue was fixed by taking the order of indexes returned by the layout into account. This does add two filters when `visible(for:)` is called on a SectionProvider. --- Sources/Provider/FlattenedProvider.swift | 38 ++++++++++++++++-------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/Sources/Provider/FlattenedProvider.swift b/Sources/Provider/FlattenedProvider.swift index 5466816..8e629bc 100644 --- a/Sources/Provider/FlattenedProvider.swift +++ b/Sources/Provider/FlattenedProvider.swift @@ -84,26 +84,27 @@ struct FlattenedProvider: ItemProvider { return provider.contentSize } - // BREAKS STICKY HEADERS func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { - let visibleFrame = provider.visible(for: visibleFrame).frame - - let indexes: [Int] = childSections.enumerated().flatMap { index, child -> [Int] in + let visible = provider.visible(for: visibleFrame) + // sort child sections by the indexes from layout + let sections = Array(0.. [Int] in let sectionFrame = provider.frame(at: index) - let intersectFrame = visibleFrame.intersection(sectionFrame) + let intersectFrame = visible.frame.intersection(sectionFrame) var visibleFrameForCell = CGRect(origin: intersectFrame.origin - sectionFrame.origin, size: intersectFrame.size) if intersectFrame.origin == .infinity { // even if there is no intersection now, there might be - // after the layout adds visible frame inset so we still - // call the section with a valid frame - visibleFrameForCell.origin = visibleFrame.origin + // after the childs layout adds visible frame inset so + // we still call the section with a valid frame + visibleFrameForCell.origin = visible.frame.origin } - let visible = child.sectionData?.visible(for: visibleFrameForCell) - let indexes = visible?.indexes ?? [0] - return indexes.map { $0 + child.beginIndex } + let child = childSections[index] + let childVisible = child.sectionData?.visible(for: visibleFrameForCell) + let childIndexes = childVisible?.indexes ?? [0] + return childIndexes.map { $0 + child.beginIndex } } - - return (indexes, visibleFrame) + return (indexes, visible.frame) } func frame(at: Int) -> CGRect { @@ -145,3 +146,14 @@ struct FlattenedProvider: ItemProvider { extension CGPoint { static var infinity: CGPoint = CGPoint(x: CGFloat.infinity, y: CGFloat.infinity) } + +extension Array where Element: Equatable { + + /// Returns an array sorted based on another array + /// + /// - Parameter array: The array with items that we sort bt + /// - Returns: An array sorted by elements in parameter array. + func sorted(by array: [Element]) -> [Element] { + return array.filter { contains($0) } + filter { !array.contains($0) } + } +} From bf0f4104c4b601065cef02d2dfa5c6561e4a7bfd Mon Sep 17 00:00:00 2001 From: Casper Zandbergen Date: Fri, 30 Nov 2018 09:25:12 +0100 Subject: [PATCH 3/7] transpose layout returns the frame in the original state, not transposed. --- Sources/Layout/TransposeLayout.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/Layout/TransposeLayout.swift b/Sources/Layout/TransposeLayout.swift index f2f9f62..f85d0a6 100644 --- a/Sources/Layout/TransposeLayout.swift +++ b/Sources/Layout/TransposeLayout.swift @@ -38,7 +38,8 @@ open class TransposeLayout: WrapperLayout { } open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { - return rootLayout.visible(for: visibleFrame.transposed) + let visible = rootLayout.visible(for: visibleFrame.transposed) + return (visible.indexes, visible.frame.transposed) } open override func frame(at: Int) -> CGRect { From 6735cbc0dd0177ac4f60b1753b37ed34ebb41b8e Mon Sep 17 00:00:00 2001 From: Casper Zandbergen Date: Fri, 30 Nov 2018 09:44:40 +0100 Subject: [PATCH 4/7] Changed to an intersection to an overlap calculation that still returns a rect for the section to add its visible frame inset to. --- Sources/Provider/FlattenedProvider.swift | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Sources/Provider/FlattenedProvider.swift b/Sources/Provider/FlattenedProvider.swift index 8e629bc..92bdf24 100644 --- a/Sources/Provider/FlattenedProvider.swift +++ b/Sources/Provider/FlattenedProvider.swift @@ -90,15 +90,21 @@ struct FlattenedProvider: ItemProvider { let sections = Array(0.. [Int] in - let sectionFrame = provider.frame(at: index) - let intersectFrame = visible.frame.intersection(sectionFrame) - var visibleFrameForCell = CGRect(origin: intersectFrame.origin - sectionFrame.origin, size: intersectFrame.size) - if intersectFrame.origin == .infinity { - // even if there is no intersection now, there might be - // after the childs layout adds visible frame inset so - // we still call the section with a valid frame - visibleFrameForCell.origin = visible.frame.origin - } + let section = provider.frame(at: index) + // intersection that doesn't return invalid frame when the + // rects don't intersect but rather returns a rect spanning + // the part of the border of the visible frame where the + // section frame would enter the visible frame if it + // were closer. This allows for the section to add its + // visible inset to that rect and show according to that. + // Calculation source https://math.stackexchange.com/a/99576 + let x = max(0, visible.frame.origin.x - section.origin.x) + let y = max(0, visible.frame.origin.y - section.origin.y) + let maxTop = max(visible.frame.origin.y, section.origin.y) + let maxLeft = max(visible.frame.origin.x, section.origin.x) + let minBottom = min(visible.frame.origin.y + visible.frame.size.height, section.origin.y + section.size.height) + let minRight = min(visible.frame.origin.x + visible.frame.size.width, section.origin.x + section.size.width) + let visibleFrameForCell = CGRect(x: x, y: y, width: minRight - maxLeft, height: minBottom - maxTop) let child = childSections[index] let childVisible = child.sectionData?.visible(for: visibleFrameForCell) let childIndexes = childVisible?.indexes ?? [0] From 76d5f457635ca8fb7f54e061502daaffcfb8e5ca Mon Sep 17 00:00:00 2001 From: Casper Zandbergen Date: Fri, 30 Nov 2018 12:41:31 +0100 Subject: [PATCH 5/7] Fix for horizontal layout inside section provider with vertical layout (or the other way around). After this fix there is one more issue: When a horizontal layout section with visible frame inset is inside a section provider with vertical layout (or the other way around) the visible frame inset is actually twice the set value. This is due to the optimised index search not checking vertical position. Right now I added a guard to not show the section when visible frame is empty instead of when there is no frames inside the visibleFrame. Not sure if this is better optimised or not. A way to fix it would be to check if rootLayout is a vertical or horizontal layout and adjusting the inset inside the VisibleFrameInset init, but this is not the root of the problem so I'm not sure how to do it instead. --- Sources/Layout/SimpleLayout.swift | 18 ++++++++++++++++++ Sources/Provider/FlattenedProvider.swift | 6 +++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Sources/Layout/SimpleLayout.swift b/Sources/Layout/SimpleLayout.swift index 148b303..b9e6bb5 100644 --- a/Sources/Layout/SimpleLayout.swift +++ b/Sources/Layout/SimpleLayout.swift @@ -55,6 +55,13 @@ open class VerticalSimpleLayout: SimpleLayout { } open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + guard !visibleFrame.isEmptyOrNegative else { + // When this vertical layout gets called in a + // section provider with horizontal layout we need + // to guard here because the optimised index search + // here doesn't take the X axes into account. + return ([], visibleFrame) + } var index = frames.binarySearch { $0.minY < visibleFrame.minY - maxFrameLength } var visibleIndexes = [Int]() while index < frames.count { @@ -79,6 +86,9 @@ open class HorizontalSimpleLayout: SimpleLayout { } open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + guard !visibleFrame.isEmptyOrNegative else { + return ([], visibleFrame) + } var index = frames.binarySearch { $0.minX < visibleFrame.minX - maxFrameLength } var visibleIndexes = [Int]() while index < frames.count { @@ -94,3 +104,11 @@ open class HorizontalSimpleLayout: SimpleLayout { return (visibleIndexes, visibleFrame) } } + +extension CGRect { + /// Returns whether a rectangle has zero or less + /// width or height, or is a null rectangle. + var isEmptyOrNegative: Bool { + return isEmpty || size.width < 0 || size.height < 0 + } +} diff --git a/Sources/Provider/FlattenedProvider.swift b/Sources/Provider/FlattenedProvider.swift index 92bdf24..b69799d 100644 --- a/Sources/Provider/FlattenedProvider.swift +++ b/Sources/Provider/FlattenedProvider.swift @@ -84,7 +84,7 @@ struct FlattenedProvider: ItemProvider { return provider.contentSize } - func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { let visible = provider.visible(for: visibleFrame) // sort child sections by the indexes from layout let sections = Array(0.. Date: Fri, 30 Nov 2018 13:42:07 +0100 Subject: [PATCH 6/7] Added comment for unexpected behaviour, we can't actually check if the insets are in the right direction because the VisibleFrameInsetLayout might get transposed later. --- Sources/Layout/Layout.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/Layout/Layout.swift b/Sources/Layout/Layout.swift index de511c1..503462c 100644 --- a/Sources/Layout/Layout.swift +++ b/Sources/Layout/Layout.swift @@ -38,6 +38,7 @@ extension Layout { return InsetLayout(self, insets: insets) } + /// Visible insets in the opposite of the layout direction are doubled public func insetVisibleFrame(by insets: UIEdgeInsets) -> VisibleFrameInsetLayout { return VisibleFrameInsetLayout(self, insets: insets) } From 910f73241f3466aaad67f480faeff531d36f3e8f Mon Sep 17 00:00:00 2001 From: Casper Zandbergen Date: Fri, 30 Nov 2018 15:30:41 +0100 Subject: [PATCH 7/7] visible(for:) to visible(in:) better english --- CollectionKitTests/FlowLayoutSpec.swift | 2 +- CollectionKitTests/WaterfallLayoutSpec.swift | 2 +- Sources/CollectionView.swift | 2 +- Sources/Layout/InsetLayout.swift | 4 ++-- Sources/Layout/Layout.swift | 2 +- Sources/Layout/SimpleLayout.swift | 6 +++--- Sources/Layout/StickyLayout.swift | 8 ++++---- Sources/Layout/TransposeLayout.swift | 4 ++-- Sources/Layout/VisibleFrameInsetLayout.swift | 4 ++-- Sources/Layout/WrapperLayout.swift | 4 ++-- Sources/Protocol/LayoutableProvider.swift | 4 ++-- Sources/Protocol/Provider.swift | 2 +- Sources/Provider/EmptyCollectionProvider.swift | 2 +- Sources/Provider/FlattenedProvider.swift | 6 +++--- 14 files changed, 26 insertions(+), 26 deletions(-) diff --git a/CollectionKitTests/FlowLayoutSpec.swift b/CollectionKitTests/FlowLayoutSpec.swift index b910261..d7f66fe 100644 --- a/CollectionKitTests/FlowLayoutSpec.swift +++ b/CollectionKitTests/FlowLayoutSpec.swift @@ -49,7 +49,7 @@ class FlowLayoutSpec: QuickSpec { it("should not display cells outside of the visible area") { let layout = FlowLayout().transposed() layout.mockLayout(parentSize: (100, 50), (50, 50), (50, 50), (50, 50), (50, 50)) - let visible = layout.visible(for: CGRect(x: 50, y: 0, width: 100, height: 50)).indexes + let visible = layout.visible(in: CGRect(x: 50, y: 0, width: 100, height: 50)).indexes expect(visible).to(equal([1, 2])) } } diff --git a/CollectionKitTests/WaterfallLayoutSpec.swift b/CollectionKitTests/WaterfallLayoutSpec.swift index 01207fc..fd68e29 100644 --- a/CollectionKitTests/WaterfallLayoutSpec.swift +++ b/CollectionKitTests/WaterfallLayoutSpec.swift @@ -46,7 +46,7 @@ class WaterfallLayoutSpec: QuickSpec { it("should not display cells outside of the visible area") { let layout = WaterfallLayout() layout.mockLayout(parentSize: (100, 50), (50, 50), (50, 50), (50, 50), (50, 50)) - let visible = layout.visible(for: CGRect(x: 0, y: 50, width: 100, height: 50)).indexes + let visible = layout.visible(in: CGRect(x: 0, y: 50, width: 100, height: 50)).indexes expect(visible).to(equal([2, 3])) } } diff --git a/Sources/CollectionView.swift b/Sources/CollectionView.swift index 1f93ccb..b45db33 100644 --- a/Sources/CollectionView.swift +++ b/Sources/CollectionView.swift @@ -158,7 +158,7 @@ open class CollectionView: UIScrollView { } private func _loadCells(forceReload: Bool) { - let newIndexes = flattenedProvider.visible(for: visibleFrame).indexes + let newIndexes = flattenedProvider.visible(in: visibleFrame).indexes // optimization: we assume that corresponding identifier for each index doesnt change unless forceReload is true. guard forceReload || diff --git a/Sources/Layout/InsetLayout.swift b/Sources/Layout/InsetLayout.swift index e701221..893bdb9 100644 --- a/Sources/Layout/InsetLayout.swift +++ b/Sources/Layout/InsetLayout.swift @@ -55,8 +55,8 @@ open class InsetLayout: WrapperLayout { rootLayout.layout(context: InsetLayoutContext(original: context, insets: insets)) } - open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { - return rootLayout.visible(for: visibleFrame.inset(by: -insets)) + open override func visible(in visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + return rootLayout.visible(in: visibleFrame.inset(by: -insets)) } open override func frame(at: Int) -> CGRect { diff --git a/Sources/Layout/Layout.swift b/Sources/Layout/Layout.swift index 503462c..ecb3543 100644 --- a/Sources/Layout/Layout.swift +++ b/Sources/Layout/Layout.swift @@ -22,7 +22,7 @@ open class Layout { fatalError("Subclass should provide its own layout") } - open func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + open func visible(in visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { fatalError("Subclass should provide its own layout") } diff --git a/Sources/Layout/SimpleLayout.swift b/Sources/Layout/SimpleLayout.swift index b9e6bb5..07df7a8 100644 --- a/Sources/Layout/SimpleLayout.swift +++ b/Sources/Layout/SimpleLayout.swift @@ -36,7 +36,7 @@ open class SimpleLayout: Layout { return frames[at] } - open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + open override func visible(in visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { var result = [Int]() for (i, frame) in frames.enumerated() { if frame.intersects(visibleFrame) { @@ -54,7 +54,7 @@ open class VerticalSimpleLayout: SimpleLayout { maxFrameLength = frames.max { $0.height < $1.height }?.height ?? 0 } - open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + open override func visible(in visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { guard !visibleFrame.isEmptyOrNegative else { // When this vertical layout gets called in a // section provider with horizontal layout we need @@ -85,7 +85,7 @@ open class HorizontalSimpleLayout: SimpleLayout { maxFrameLength = frames.max { $0.width < $1.width }?.width ?? 0 } - open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + open override func visible(in visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { guard !visibleFrame.isEmptyOrNegative else { return ([], visibleFrame) } diff --git a/Sources/Layout/StickyLayout.swift b/Sources/Layout/StickyLayout.swift index d8d26ff..39b5e6a 100644 --- a/Sources/Layout/StickyLayout.swift +++ b/Sources/Layout/StickyLayout.swift @@ -34,19 +34,19 @@ public class StickyLayout: WrapperLayout { } } - // TODO: Fix for the new FlattenedProvider.visible(for:) - public override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + // TODO: Fix for the new FlattenedProvider.visible(in:) + public override func visible(in visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { self.visibleFrame = visibleFrame topFrameIndex = stickyFrames.binarySearch { $0.frame.minY < visibleFrame.minY } - 1 if let index = stickyFrames.get(topFrameIndex)?.index, index >= 0 { - var oldVisible = rootLayout.visible(for: visibleFrame) + var oldVisible = rootLayout.visible(in: visibleFrame) if let index = oldVisible.indexes.index(of: index) { oldVisible.indexes.remove(at: index) } oldVisible.indexes += [index] return oldVisible } - return rootLayout.visible(for: visibleFrame) + return rootLayout.visible(in: visibleFrame) } public override func frame(at: Int) -> CGRect { diff --git a/Sources/Layout/TransposeLayout.swift b/Sources/Layout/TransposeLayout.swift index f85d0a6..5825404 100644 --- a/Sources/Layout/TransposeLayout.swift +++ b/Sources/Layout/TransposeLayout.swift @@ -37,8 +37,8 @@ open class TransposeLayout: WrapperLayout { rootLayout.layout(context: TransposeLayoutContext(original: context)) } - open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { - let visible = rootLayout.visible(for: visibleFrame.transposed) + open override func visible(in visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + let visible = rootLayout.visible(in: visibleFrame.transposed) return (visible.indexes, visible.frame.transposed) } diff --git a/Sources/Layout/VisibleFrameInsetLayout.swift b/Sources/Layout/VisibleFrameInsetLayout.swift index 576e7e8..6ab3755 100644 --- a/Sources/Layout/VisibleFrameInsetLayout.swift +++ b/Sources/Layout/VisibleFrameInsetLayout.swift @@ -30,7 +30,7 @@ open class VisibleFrameInsetLayout: WrapperLayout { super.layout(context: context) } - open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { - return rootLayout.visible(for: visibleFrame.inset(by: insets)) + open override func visible(in visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + return rootLayout.visible(in: visibleFrame.inset(by: insets)) } } diff --git a/Sources/Layout/WrapperLayout.swift b/Sources/Layout/WrapperLayout.swift index 04cf7c6..a7a40d1 100644 --- a/Sources/Layout/WrapperLayout.swift +++ b/Sources/Layout/WrapperLayout.swift @@ -23,8 +23,8 @@ open class WrapperLayout: Layout { rootLayout.layout(context: context) } - open override func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { - return rootLayout.visible(for: visibleFrame) + open override func visible(in visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + return rootLayout.visible(in: visibleFrame) } open override func frame(at: Int) -> CGRect { diff --git a/Sources/Protocol/LayoutableProvider.swift b/Sources/Protocol/LayoutableProvider.swift index df683ff..c890536 100644 --- a/Sources/Protocol/LayoutableProvider.swift +++ b/Sources/Protocol/LayoutableProvider.swift @@ -21,8 +21,8 @@ extension LayoutableProvider where Self: Provider { public func layout(collectionSize: CGSize) { internalLayout.layout(context: layoutContext(collectionSize: collectionSize)) } - public func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { - return internalLayout.visible(for: visibleFrame) + public func visible(in visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + return internalLayout.visible(in: visibleFrame) } public var contentSize: CGSize { return internalLayout.contentSize diff --git a/Sources/Protocol/Provider.swift b/Sources/Protocol/Provider.swift index 8578842..6013cc7 100644 --- a/Sources/Protocol/Provider.swift +++ b/Sources/Protocol/Provider.swift @@ -17,7 +17,7 @@ public protocol Provider { // layout func layout(collectionSize: CGSize) - func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) + func visible(in visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) var contentSize: CGSize { get } func frame(at: Int) -> CGRect diff --git a/Sources/Provider/EmptyCollectionProvider.swift b/Sources/Provider/EmptyCollectionProvider.swift index 3147661..a7b3c41 100644 --- a/Sources/Provider/EmptyCollectionProvider.swift +++ b/Sources/Provider/EmptyCollectionProvider.swift @@ -33,7 +33,7 @@ open class EmptyCollectionProvider: ItemProvider, CollectionReloadable { open func frame(at: Int) -> CGRect { return .zero } - open func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + open func visible(in visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { return ([Int](), visibleFrame) } diff --git a/Sources/Provider/FlattenedProvider.swift b/Sources/Provider/FlattenedProvider.swift index b69799d..d726c0c 100644 --- a/Sources/Provider/FlattenedProvider.swift +++ b/Sources/Provider/FlattenedProvider.swift @@ -84,8 +84,8 @@ struct FlattenedProvider: ItemProvider { return provider.contentSize } - func visible(for visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { - let visible = provider.visible(for: visibleFrame) + func visible(in visibleFrame: CGRect) -> (indexes: [Int], frame: CGRect) { + let visible = provider.visible(in: visibleFrame) // sort child sections by the indexes from layout let sections = Array(0..