Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions Sources/Algorithm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
///
/// - Complexity: O(n)
@inlinable
public init(source: Collection, target: Collection) {
init(source: Collection, target: Collection) {
self.init(source: source, target: target, section: 0)
}

Expand All @@ -44,7 +44,7 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
///
/// - Complexity: O(n)
@inlinable
public init(source: Collection, target: Collection, section: Int) {
init(source: Collection, target: Collection, section: Int) {
let sourceElements = ContiguousArray(source)
let targetElements = ContiguousArray(target)

Expand Down Expand Up @@ -151,7 +151,7 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
///
/// - Complexity: O(n)
@inlinable
public init(source: Collection, target: Collection) {
init(source: Collection, target: Collection) {
typealias Section = Collection.Element
typealias SectionIdentifier = Collection.Element.DifferenceIdentifier
typealias Element = Collection.Element.Collection.Element
Expand Down Expand Up @@ -326,9 +326,15 @@ public extension StagedChangeset where Collection: RangeReplaceableCollection, C
fourthStageElements.reserveCapacity(targetElements.count)

for targetElementIndex in targetElements.indices {
#if swift(>=5.0)
untrackedSourceIndex = untrackedSourceIndex.flatMap { index in
sourceElementTraces[sourceSectionIndex].suffix(from: index).firstIndex { !$0.isTracked }
}
#else
untrackedSourceIndex = untrackedSourceIndex.flatMap { index in
sourceElementTraces[sourceSectionIndex].suffix(from: index).index { !$0.isTracked }
}
#endif

let targetElementPath = ElementPath(element: targetElementIndex, section: targetSectionIndex)
let targetElement = contiguousTargetSections[targetElementPath]
Expand Down Expand Up @@ -536,9 +542,15 @@ internal func differentiate<E: Differentiable, I>(

// Record the updates/moves/insertions.
for targetIndex in target.indices {
#if swift(>=5.0)
untrackedSourceIndex = untrackedSourceIndex.flatMap { index in
sourceTraces.suffix(from: index).firstIndex { !$0.isTracked }
}
#else
untrackedSourceIndex = untrackedSourceIndex.flatMap { index in
sourceTraces.suffix(from: index).index { !$0.isTracked }
}
#endif

if let sourceIndex = targetReferences[targetIndex] {
sourceTraces[sourceIndex].isTracked = true
Expand Down Expand Up @@ -653,14 +665,11 @@ internal final class IndicesReference {
/// Dictionary key using UnsafePointer for performance optimization.
@usableFromInline
internal struct TableKey<T: Hashable>: Hashable {
@usableFromInline
internal let hashValue: Int
@usableFromInline
internal let pointer: UnsafePointer<T>

@inlinable
internal init(pointer: UnsafePointer<T>) {
self.hashValue = pointer.pointee.hashValue
self.pointer = pointer
}

Expand All @@ -669,11 +678,15 @@ internal struct TableKey<T: Hashable>: Hashable {
return lhs.hashValue == rhs.hashValue
&& (lhs.pointer.distance(to: rhs.pointer) == 0 || lhs.pointer.pointee == rhs.pointer.pointee)
}

public func hash(into hasher: inout Hasher) {
hasher.combine(pointer.pointee)
}
}

internal extension MutableCollection where Element: MutableCollection, Index == Int, Element.Index == Int {
@inlinable
internal subscript(path: ElementPath) -> Element.Element {
subscript(path: ElementPath) -> Element.Element {
get { return self[path.section][path.element] }
set { self[path.section][path.element] = newValue }
}
Expand Down
12 changes: 6 additions & 6 deletions Sources/Changeset.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public struct Changeset<Collection: Swift.Collection> {
public extension Changeset {
/// The number of section changes.
@inlinable
public var sectionChangeCount: Int {
var sectionChangeCount: Int {
return sectionDeleted.count
+ sectionInserted.count
+ sectionUpdated.count
Expand All @@ -74,7 +74,7 @@ public extension Changeset {

/// The number of element changes.
@inlinable
public var elementChangeCount: Int {
var elementChangeCount: Int {
return elementDeleted.count
+ elementInserted.count
+ elementUpdated.count
Expand All @@ -83,25 +83,25 @@ public extension Changeset {

/// The number of all changes.
@inlinable
public var changeCount: Int {
var changeCount: Int {
return sectionChangeCount + elementChangeCount
}

/// A Boolean value indicating whether has section changes.
@inlinable
public var hasSectionChanges: Bool {
var hasSectionChanges: Bool {
return sectionChangeCount > 0
}

/// A Boolean value indicating whether has element changes.
@inlinable
public var hasElementChanges: Bool {
var hasElementChanges: Bool {
return elementChangeCount > 0
}

/// A Boolean value indicating whether has changes.
@inlinable
public var hasChanges: Bool {
var hasChanges: Bool {
return changeCount > 0
}
}
Expand Down
18 changes: 18 additions & 0 deletions Sources/Extensions/AppKitExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,23 @@ public extension NSTableView {
/// updates should be stopped and performed reloadData. Default is nil.
/// - setData: A closure that takes the collection as a parameter.
/// The collection should be set to data-source of NSTableView.
#if swift(>=5.0)
func reload<C>(
using stagedChangeset: StagedChangeset<C>,
with animation: @autoclosure () -> NSTableView.AnimationOptions,
interrupt: ((Changeset<C>) -> Bool)? = nil,
setData: (C) -> Void
) {
reload(
using: stagedChangeset,
deleteRowsAnimation: animation(),
insertRowsAnimation: animation(),
reloadRowsAnimation: animation(),
interrupt: interrupt,
setData: setData
)
}
#else
func reload<C>(
using stagedChangeset: StagedChangeset<C>,
with animation: @autoclosure () -> NSTableView.AnimationOptions,
Expand All @@ -30,6 +47,7 @@ public extension NSTableView {
setData: setData
)
}
#endif

/// Applies multiple animated updates in stages using `StagedChangeset`.
///
Expand Down
36 changes: 36 additions & 0 deletions Sources/StagedChangeset.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,41 @@ public struct StagedChangeset<Collection: Swift.Collection> {
}
}

#if compiler(>=5.0)
/* Removes MutableCollection conformance as it is redundant. */
extension StagedChangeset: RandomAccessCollection, RangeReplaceableCollection {
@inlinable
public init() {
self.init([])
}

@inlinable
public var startIndex: Int {
return changesets.startIndex
}

@inlinable
public var endIndex: Int {
return changesets.endIndex
}

@inlinable
public func index(after i: Int) -> Int {
return changesets.index(after: i)
}

@inlinable
public subscript(position: Int) -> Changeset<Collection> {
get { return changesets[position] }
set { changesets[position] = newValue }
}

@inlinable
public mutating func replaceSubrange<C: Swift.Collection, R: RangeExpression>(_ subrange: R, with newElements: C) where C.Element == Changeset<Collection>, R.Bound == Int {
changesets.replaceSubrange(subrange, with: newElements)
}
}
#else
extension StagedChangeset: RandomAccessCollection, RangeReplaceableCollection, MutableCollection {
@inlinable
public init() {
Expand Down Expand Up @@ -75,6 +110,7 @@ extension StagedChangeset: RandomAccessCollection, RangeReplaceableCollection, M
changesets.replaceSubrange(subrange, with: newElements)
}
}
#endif

extension StagedChangeset: Equatable where Collection: Equatable {
@inlinable
Expand Down