Simplest way to do both expand and collapse together seems to be target/action with single clicks. I had tried overriding the selection functions in the outlineview delegate, and that worked for expansion but not collapse. Code below for single click expand/collapse:
[self.myOutlineView setTarget:self]; // Needed if not done in IB
[self.myOutlineView setAction:@selector(outlineViewClicked:)];
[self.myOutlineView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone];
- (void) outlineViewClicked:(NSOutlineView*)sender
{
id clickItem = [sender itemAtRow:[self.itemsOutlineView clickedRow]];
if (clickItem)
{
BOOL optionPressed = (([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) == NSAlternateKeyMask);
[sender isItemExpanded:clickItem] ?
[sender.animator collapseItem:clickItem collapseChildren:optionPressed] :
[sender.animator expandItem:clickItem expandChildren:optionPressed];
}
}
Expanding that to collapse siblings:
- (void) outlineViewClicked:(NSOutlineView*)sender
{
id clickItem = [sender itemAtRow:[self.itemsOutlineView clickedRow]];
if (!clickItem)
return;
BOOL optionPressed = (([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) == NSAlternateKeyMask);
// Collapse the sibling nodes (tree controller type NSTreeNode)
for (NSTreeNode* node in ((NSTreeNode*)clickItem).parentNode.childNodes)
{
if (node != clickItem && [sender isItemExpanded:node])
[sender.animator collapseItem:node];
}
[sender isItemExpanded:clickItem] ?
[sender.animator collapseItem:clickItem collapseChildren:optionPressed] : [sender.animator expandItem:clickItem expandChildren:optionPressed];
}
The optionPressed
BOOL and the subsequent use in expandChildren
and collapseChildren
was suggested by @ben-haller, who noted that "an option-click on the disclosure triangle expands or collapses all of its contained items." (Quoted from About Outline Views) Ben's modification extends that option-click behavior to the "anywhere in the row" methods here.