diff --git a/Sources/SelectableCollectionView/Views/CollectionViewContainer.swift b/Sources/SelectableCollectionView/Views/CollectionViewContainer.swift index 73a92d7..d7789d1 100644 --- a/Sources/SelectableCollectionView/Views/CollectionViewContainer.swift +++ b/Sources/SelectableCollectionView/Views/CollectionViewContainer.swift @@ -26,22 +26,26 @@ import SwiftUI import SelectableCollectionViewMacResources -#warning("TODO: Rename element to ID to avoid confusion?") - -protocol CollectionViewContainerDelegate: NSObject { - func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, - menuItemsForElements elements: Set) -> [MenuItem] - func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, - contentForElement element: Element) -> Content? - func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, - didUpdateSelection selection: Set) - func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, - didDoubleClickSelection selection: Set) - - func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, - keyDown event: NSEvent) -> Bool - func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, - keyUp event: NSEvent) -> Bool +// TODO: Rename element to ID to avoid confusion? + +public protocol CollectionViewContainerDelegate: NSObject { + + associatedtype Element: Hashable & Identifiable + associatedtype CellContent: View + + func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, + menuItemsForElements elements: Set) -> [MenuItem] + func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, + contentForElement element: Element) -> CellContent? + func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, + didUpdateSelection selection: Set) + func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, + didDoubleClickSelection selection: Set) + + func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, + keyDown event: NSEvent) -> Bool + func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, + keyUp event: NSEvent) -> Bool } class CustomScrollView: NSScrollView { @@ -64,12 +68,14 @@ class CustomScrollView: NSScrollView { } -public class CollectionViewContainer: NSView, - NSCollectionViewDelegate, - CollectionViewInteractionDelegate, - NSCollectionViewDelegateFlowLayout { +public class CollectionViewContainer +: NSView, + NSCollectionViewDelegate, + CollectionViewInteractionDelegate, + NSCollectionViewDelegateFlowLayout where Delegate.Element == Element, + Delegate.CellContent == Content { - weak var delegate: CollectionViewContainerDelegate? + weak var delegate: Delegate? enum Section { case none diff --git a/Sources/SelectableCollectionView/Views/CollectionViewContainerHost.swift b/Sources/SelectableCollectionView/Views/CollectionViewContainerHost.swift index 6f2128f..929f0fd 100644 --- a/Sources/SelectableCollectionView/Views/CollectionViewContainerHost.swift +++ b/Sources/SelectableCollectionView/Views/CollectionViewContainerHost.swift @@ -23,14 +23,18 @@ import SwiftUI public struct CollectionViewContainerHost: NSViewRepresentable where Data.Element: Identifiable, - Data.Element: Hashable, - Data.Element.ID: Hashable { + Content: View> +: NSViewRepresentable where Data.Element: Identifiable, + Data.Element: Hashable, + Data.Element.ID: Hashable { public typealias ID = Data.Element.ID public typealias Element = Data.Element - public class Coordinator: NSObject, CollectionViewContainerDelegate { + public final class Coordinator: NSObject, CollectionViewContainerDelegate { + + public typealias Element = Data.Element + public typealias CellContent = Content var parent: CollectionViewContainerHost var collectionViewLayoutHash: Int = 0 @@ -39,50 +43,36 @@ public struct CollectionViewContainerHost(_ collectionViewContainer: CollectionViewContainer, - menuItemsForElements elements: Set) -> [MenuItem] where Element : Hashable, Content : View { - guard let elements = elements as? Set else { - return [] - } + public func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, + menuItemsForElements elements: Set) -> [MenuItem] { let ids = Set(elements.map { $0.id }) return parent.contextMenu(ids) } - func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, - contentForElement element: Element) -> Content? where Element : Hashable, Content : View { -#warning("TODO: These guards shouldn't be necessary?") - guard let element = element as? Data.Element, - let content = parent.itemContent(element) as? Content else { - return nil - } - return content + public func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, + contentForElement element: Element) -> Content? { + return parent.itemContent(element) } - func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, - didUpdateSelection selection: Set) where Element : Hashable, Content : View { - guard let selection = selection as? Set else { - return - } + public func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, + didUpdateSelection selection: Set) { let ids = Set(selection.map { $0.id }) parent.selection.wrappedValue = ids } - func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, - didDoubleClickSelection selection: Set) where Element : Hashable, Content : View { - guard let selection = selection as? Set else { - return - } + public func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, + didDoubleClickSelection selection: Set) { let ids = Set(selection.map { $0.id }) parent.primaryAction(ids) } - func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, - keyDown event: NSEvent) -> Bool where Element : Hashable, Content : View { + public func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, + keyDown event: NSEvent) -> Bool { return parent.keyDown(event) } - func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, - keyUp event: NSEvent) -> Bool where Element : Hashable, Content : View { + public func collectionViewContainer(_ collectionViewContainer: CollectionViewContainer, + keyUp event: NSEvent) -> Bool { return parent.keyUp(event) } @@ -119,15 +109,14 @@ public struct CollectionViewContainerHost CollectionViewContainer { - let collectionView = CollectionViewContainer(layout: layout.makeLayout()) + public func makeNSView(context: Context) -> CollectionViewContainer { + let collectionView = CollectionViewContainer(layout: layout.makeLayout()) collectionView.delegate = context.coordinator return collectionView } - public func updateNSView(_ collectionView: CollectionViewContainer, context: Context) { + public func updateNSView(_ collectionView: CollectionViewContainer, context: Context) { context.coordinator.parent = self -#warning("TODO: We shouldn't need to copy this into an array?") let selectedElements = items.filter { selection.wrappedValue.contains($0.id) } collectionView.update(Array(items), selection: Set(selectedElements)) @@ -137,7 +126,6 @@ public struct CollectionViewContainerHost