From 1047fa5a0210e05e9663b9a434825f2a524447a7 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 25 Nov 2017 17:44:54 -0800 Subject: [PATCH] Use the proper index sets and so on to make deleting work from the sidebar again. Fix #192. --- .../Sidebar/SidebarViewController.swift | 31 +++++++++++--- Frameworks/RSTree/RSTree/Node.swift | 41 ++++++++++++++++++- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/Evergreen/MainWindow/Sidebar/SidebarViewController.swift b/Evergreen/MainWindow/Sidebar/SidebarViewController.swift index 0da6ba0d2..2ec925aa9 100644 --- a/Evergreen/MainWindow/Sidebar/SidebarViewController.swift +++ b/Evergreen/MainWindow/Sidebar/SidebarViewController.swift @@ -111,14 +111,17 @@ import RSCore return } - let selectedRows = outlineView.selectedRowIndexes - animatingChanges = true outlineView.beginUpdates() - outlineView.removeItems(at: selectedRows, inParent: nil, withAnimation: [.slideDown]) - outlineView.endUpdates() - runCommand(deleteCommand) + let indexSetsGroupedByParent = Node.indexSetsGroupedByParent(nodesToDelete) + for (parent, indexSet) in indexSetsGroupedByParent { + outlineView.removeItems(at: indexSet, inParent: parent.isRoot ? nil : parent, withAnimation: [.slideDown]) + } + + outlineView.endUpdates() + + runCommand(deleteCommand) animatingChanges = false } @@ -465,6 +468,22 @@ private extension SidebarViewController { deleteItemForNode(oneNode) } } - + + func commonParentItemForNodes(_ nodes: [Node]) -> Node? { + + if nodes.isEmpty { + return nil + } + + guard let parent = nodes.first!.parent else { + return nil + } + for node in nodes { + if node.parent !== parent { + return nil + } + } + return parent + } } diff --git a/Frameworks/RSTree/RSTree/Node.swift b/Frameworks/RSTree/RSTree/Node.swift index 4b40710a0..618bad9d4 100644 --- a/Frameworks/RSTree/RSTree/Node.swift +++ b/Frameworks/RSTree/RSTree/Node.swift @@ -8,14 +8,17 @@ import Foundation -public final class Node: Equatable { +public final class Node: Hashable { public weak var parent: Node? public let representedObject: AnyObject public var canHaveChildNodes = false public var isGroupItem = false public var childNodes: [Node]? - + public let hashValue: Int + private static var incrementingID = 0 + private static var incrementingIDLock = NSLock() + public var isRoot: Bool { get { if let _ = parent { @@ -63,6 +66,11 @@ public final class Node: Equatable { self.representedObject = representedObject self.parent = parent + + Node.incrementingIDLock.lock() + self.hashValue = Node.incrementingID + Node.incrementingID += 1 + Node.incrementingIDLock.unlock() } public class func genericRootNode() -> Node { @@ -137,6 +145,35 @@ public final class Node: Equatable { nomad = parent } } + + public class func nodesOrganizedByParent(_ nodes: [Node]) -> [Node: [Node]] { + + let nodesWithParents = nodes.filter { $0.parent != nil } + return Dictionary(grouping: nodesWithParents, by: { $0.parent! }) + } + + public class func indexSetsGroupedByParent(_ nodes: [Node]) -> [Node: IndexSet] { + + let d = nodesOrganizedByParent(nodes) + let indexSetDictionary = d.mapValues { (nodes) -> IndexSet in + + var indexSet = IndexSet() + if nodes.isEmpty { + return indexSet + } + + let parent = nodes.first!.parent! + for node in nodes { + if let index = parent.indexOfChild(node) { + indexSet.insert(index) + } + } + + return indexSet + } + + return indexSetDictionary + } }