From 537e3da29e18fde416baa5cbc59d9f09e135ebc9 Mon Sep 17 00:00:00 2001 From: Roman Podymov Date: Tue, 9 Apr 2024 06:57:23 +0200 Subject: [PATCH] Footer --- Sources/CommonAppleKit/CAListView.swift | 34 ++++++++++++++-- .../CommonAppleKit/CAScrollableListView.swift | 39 ++++++++++++++++--- Sources/CommonAppleKit/CommonAppleKit.swift | 22 +++++++++++ 3 files changed, 87 insertions(+), 8 deletions(-) diff --git a/Sources/CommonAppleKit/CAListView.swift b/Sources/CommonAppleKit/CAListView.swift index c801615..9ad768a 100644 --- a/Sources/CommonAppleKit/CAListView.swift +++ b/Sources/CommonAppleKit/CAListView.swift @@ -7,9 +7,16 @@ // import Foundation - -open class CAListView, CellRootView, CellDataType>: CACollectionView, CACollectionViewDataSource, CACollectionViewDelegate { +import CoreGraphics + +open class CAListView< + Cell: CAListViewCell, + Footer: CACollectionReusableView, + CellRootView, + CellDataType +>: CACollectionView, CACollectionViewDataSource, CACollectionViewDelegate { private let cellId: String + private let footerId: String private weak var cellDelegate: CAListViewCellDelegate? #if canImport(UIKit) @@ -35,15 +42,19 @@ open class CAListView, CellRootView, CellData itemSize: CGSize, minimumInteritemSpacing: CGFloat = 0, minimumLineSpacing: CGFloat = 0, + footerReferenceSize: CGSize = .zero, cellId: String = .init(describing: Cell.self), - cellDelegate: CAListViewCellDelegate? = nil + cellDelegate: CAListViewCellDelegate? = nil, + footerId: String = .init(describing: Footer.self) ) { self.cellId = cellId + self.footerId = footerId self.cellDelegate = cellDelegate let layout = CACollectionViewFlowLayout() layout.itemSize = itemSize layout.minimumInteritemSpacing = minimumInteritemSpacing layout.minimumLineSpacing = minimumLineSpacing + layout.footerReferenceSize = footerReferenceSize #if canImport(AppKit) super.init(frame: frame) collectionViewLayout = layout @@ -52,6 +63,11 @@ open class CAListView, CellRootView, CellData #endif register(Cell.self, forCellWithReuseIdentifier: cellId) + register( + Footer.self, + forSupplementaryViewOfKind: CACollectionView.elementKindSectionFooter, + withReuseIdentifier: footerId + ) delegate = self #if canImport(UIKit) @@ -67,6 +83,18 @@ open class CAListView, CellRootView, CellData content.count } + public func collectionView(_ collectionView: CACollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> CACollectionReusableView { + if kind == CACollectionView.elementKindSectionFooter { + let view = collectionView.dequeueReusableSupplementaryView( + ofKind: CACollectionView.elementKindSectionFooter, + withReuseIdentifier: footerId, + for: indexPath + ) + return view + } + return .init() + } + #if canImport(AppKit) public func collectionView(_ collectionView: CACollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> CACollectionViewCell { collectionView.makeItem(withIdentifier: .init(cellId), for: indexPath) diff --git a/Sources/CommonAppleKit/CAScrollableListView.swift b/Sources/CommonAppleKit/CAScrollableListView.swift index 9230f2a..05e2610 100644 --- a/Sources/CommonAppleKit/CAScrollableListView.swift +++ b/Sources/CommonAppleKit/CAScrollableListView.swift @@ -7,18 +7,42 @@ // import Foundation +import CoreGraphics #if canImport(AppKit) -open class CAScrollableListView, CellRootView, CellDataType>: CAScrollView { +open class CAScrollableListView< + Cell: CAListViewCell, + Footer: CACollectionReusableView, + CellRootView, + CellDataType +>: CAScrollView { public var content: [CellDataType] = [] { didSet { - (documentView as? CAListView)?.content = content + (documentView as? CAListView)?.content = content } } - public init(frame: CGRect, itemSize: CGSize, cellId: String = .init(describing: Cell.self), cellDelegate: CAListViewCellDelegate? = nil) { + public init( + frame: CGRect, + itemSize: CGSize, + minimumInteritemSpacing: CGFloat = 0, + minimumLineSpacing: CGFloat = 0, + footerReferenceSize: CGSize = .zero, + cellId: String = .init(describing: Cell.self), + cellDelegate: CAListViewCellDelegate? = nil, + footerId: String = .init(describing: Footer.self) + ) { super.init(frame: frame) - let listView = CAListView(frame: frame, itemSize: itemSize, cellId: cellId, cellDelegate: cellDelegate) + let listView = CAListView( + frame: frame, + itemSize: itemSize, + minimumInteritemSpacing: minimumInteritemSpacing, + minimumLineSpacing: minimumLineSpacing, + footerReferenceSize: footerReferenceSize, + cellId: cellId, + cellDelegate: cellDelegate, + footerId: footerId + ) documentView = listView } @@ -27,7 +51,12 @@ open class CAScrollableListView, CellRootView } } #elseif canImport(UIKit) -open class CAScrollableListView, CellRootView, CellDataType>: CAListView { +open class CAScrollableListView< + Cell: CAListViewCell, + Footer: CACollectionReusableView, + CellRootView, + CellDataType +>: CAListView { open var documentView: CAView? { self } diff --git a/Sources/CommonAppleKit/CommonAppleKit.swift b/Sources/CommonAppleKit/CommonAppleKit.swift index 706abee..9f3e274 100644 --- a/Sources/CommonAppleKit/CommonAppleKit.swift +++ b/Sources/CommonAppleKit/CommonAppleKit.swift @@ -28,6 +28,7 @@ public typealias CAScrollView = UIScrollView public typealias CACollectionView = UICollectionView public typealias CACollectionViewCell = UICollectionViewCell + public typealias CACollectionReusableView = UICollectionReusableView public typealias CALabel = UILabel public typealias CACollectionViewDataSource = UICollectionViewDataSource public typealias CACollectionViewDelegate = UICollectionViewDelegate @@ -165,6 +166,7 @@ public typealias CAScrollView = NSScrollView public typealias CACollectionView = NSCollectionView public typealias CACollectionViewCell = NSCollectionViewItem + public typealias CACollectionReusableView = NSView public typealias CALabel = NSTextField public typealias CACollectionViewDataSource = NSCollectionViewDataSource public typealias CACollectionViewDelegate = NSCollectionViewDelegate @@ -273,6 +275,26 @@ ) { register(cellClass, forItemWithIdentifier: .init(identifier)) } + + func register( + _ viewClass: AnyClass?, + forSupplementaryViewOfKind elementKind: String, + withReuseIdentifier identifier: String + ) { + register( + viewClass, + forSupplementaryViewOfKind: elementKind, + withIdentifier: .init(identifier) + ) + } + + func dequeueReusableSupplementaryView( + ofKind elementKind: String, + withReuseIdentifier identifier: String, + for indexPath: IndexPath + ) -> CACollectionReusableView { + makeSupplementaryView(ofKind: elementKind, withIdentifier: .init(identifier), for: indexPath) + } } public extension CAWindow {