Search code examples
cocoansoutlineview

NSOutlineView detect when children are collapsed


I'm trying to store the actual collapsed/expanded state of items in a NSOutlineView, such that it can be restored later. There are two methods available on NSOutlineViewDelegate:

  • outlineViewItemDidExpand(Notification)
  • outlineViewItemDidCollapse(Notification)

The problem is that these methods are not only called for the item the user clicks on, but for collapsible children as well. Example:

- a
-- b
--- c

When a is collapsed outlineViewItemDidCollapse is called twice, once for b and once for a. Marking both as collapsed is incorrect, since b should still be expanded and c should be visible after expanding a again. So the actual state for b should be expanded.

When a user Option-clicks on a all children are collapsed as well (outlineView.collapseItem(item, collapseChildren: true)). After expanding a again, b should stay collapsed. The state for b should be collapsed in this case.

The two different states:

  • a: collapsed, b: expanded (but hidden due to parent)
  • a: collapsed, b: collapsed (and hidden due to parent)

Is there any way to differentiate between these two actions/states, such that I can properly restore it later?


Solution

  • Some ideas:

    NSOutlineView can save and restore the expanded items (autosaveExpandedItems). The settings can be retrieved from NSUserDefaults. The key is NSOutlineView Items <autosaveName>.

    Subclass NSOutlineView and override expandItem(_:expandChildren:) and collapseItem(_:collapseChildren:). The methods are not called for the children.

    It might be possible to figure out which item is expanded or collapsed using the current event in outlineViewItemWillExpand(_:) and outlineViewItemWillCollapse(_:).