Save sidebar expanded state.

This commit is contained in:
Maurice Parker 2020-03-03 17:10:03 -08:00
parent 94d04e3cc2
commit ae8f36d300
1 changed files with 54 additions and 13 deletions

View File

@ -18,7 +18,7 @@ protocol SidebarDelegate: class {
func sidebarInvalidatedRestorationState(_: SidebarViewController) func sidebarInvalidatedRestorationState(_: SidebarViewController)
} }
@objc class SidebarViewController: NSViewController, NSOutlineViewDelegate, NSOutlineViewDataSource, NSMenuDelegate, UndoableCommandRunner { @objc class SidebarViewController: NSViewController, NSOutlineViewDelegate, NSMenuDelegate, UndoableCommandRunner {
@IBOutlet var outlineView: SidebarOutlineView! @IBOutlet var outlineView: SidebarOutlineView!
@ -39,9 +39,9 @@ protocol SidebarDelegate: class {
} }
set { set {
treeControllerDelegate.isReadFiltered = newValue treeControllerDelegate.isReadFiltered = newValue
delegate?.sidebarInvalidatedRestorationState(self)
} }
} }
var expandedTable = Set<ContainerIdentifier>()
var undoableCommands = [UndoableCommand]() var undoableCommands = [UndoableCommand]()
private var animatingChanges = false private var animatingChanges = false
@ -77,28 +77,31 @@ protocol SidebarDelegate: class {
outlineView.reloadData() outlineView.reloadData()
// Always expand all group items on initial display. // Expand top level items by default. If there is state to restore, overlay this.
var row = 0 for topLevelNode in treeController.rootNode.childNodes {
while(true) { if let containerID = (topLevelNode.representedObject as? ContainerIdentifiable)?.containerID {
guard let item = outlineView.item(atRow: row) else { expandedTable.insert(containerID)
break
} }
let node = item as! Node
if node.isGroupItem {
outlineView.expandItem(item)
}
row += 1
} }
expandNodes()
} }
// MARK: State Restoration // MARK: State Restoration
func saveState(to coder: NSCoder) { func saveState(to coder: NSCoder) {
coder.encode(isReadFiltered, forKey: UserInfoKey.readFeedsFilterState) coder.encode(isReadFiltered, forKey: UserInfoKey.readFeedsFilterState)
coder.encode(expandedTable.map( { $0.userInfo }), forKey: UserInfoKey.containerExpandedWindowState)
} }
func restoreState(from coder: NSCoder) { func restoreState(from coder: NSCoder) {
isReadFiltered = coder.decodeBool(forKey: UserInfoKey.readFeedsFilterState) isReadFiltered = coder.decodeBool(forKey: UserInfoKey.readFeedsFilterState)
if let containerExpandedWindowState = try? coder.decodeTopLevelObject(forKey: UserInfoKey.containerExpandedWindowState) as? [[AnyHashable: AnyHashable]] {
let containerIdentifers = containerExpandedWindowState.compactMap( { ContainerIdentifier(userInfo: $0) })
expandedTable = Set(containerIdentifers)
}
rebuildTreeAndRestoreSelection() rebuildTreeAndRestoreSelection()
} }
@ -320,6 +323,28 @@ protocol SidebarDelegate: class {
selectionDidChange(selectedObjects.isEmpty ? nil : selectedObjects) selectionDidChange(selectedObjects.isEmpty ? nil : selectedObjects)
} }
func outlineViewItemDidExpand(_ notification: Notification) {
guard let node = notification.userInfo?["NSObject"] as? Node,
let containerID = (node.representedObject as? ContainerIdentifiable)?.containerID else {
return
}
if !expandedTable.contains(containerID) {
expandedTable.insert(containerID)
delegate?.sidebarInvalidatedRestorationState(self)
}
}
func outlineViewItemDidCollapse(_ notification: Notification) {
guard let node = notification.userInfo?["NSObject"] as? Node,
let containerID = (node.representedObject as? ContainerIdentifiable)?.containerID else {
return
}
if expandedTable.contains(containerID) {
expandedTable.remove(containerID)
delegate?.sidebarInvalidatedRestorationState(self)
}
}
//MARK: - Node Manipulation //MARK: - Node Manipulation
func deleteNodes(_ nodes: [Node]) { func deleteNodes(_ nodes: [Node]) {
@ -378,6 +403,7 @@ protocol SidebarDelegate: class {
} else { } else {
isReadFiltered = true isReadFiltered = true
} }
delegate?.sidebarInvalidatedRestorationState(self)
rebuildTreeAndRestoreSelection() rebuildTreeAndRestoreSelection()
} }
@ -487,6 +513,21 @@ private extension SidebarViewController {
treeController.rebuild() treeController.rebuild()
treeControllerDelegate.resetFilterExceptions() treeControllerDelegate.resetFilterExceptions()
outlineView.reloadData() outlineView.reloadData()
expandNodes()
}
}
func expandNodes() {
treeController.visitNodes(expandNodesVisitor(node:))
}
func expandNodesVisitor(node: Node) {
if let containerID = (node.representedObject as? ContainerIdentifiable)?.containerID {
if expandedTable.contains(containerID) {
outlineView.expandItem(node)
} else {
outlineView.collapseItem(node)
}
} }
} }