Question

What is the most expedient way to expand NSOutlineView rows on a single click of the entire row? (not the disclosure triangle)

Is there a single setting for this? Or some magical mode setting that changes the behavior similar to source list style?

Était-ce utile?

La solution

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.

Autres conseils

Swift version:

outlineView.target = self
outlineView.action = #selector(outlineViewClicked(_:))

@objc private func outlineViewClicked(_ sender: NSOutlineView) {
    expandOrCollapseRow(outlineView: sender)
}

private func expandOrCollapseRow(outlineView: NSOutlineView) {
    if let clickedItem = outlineView.item(atRow: outlineView.clickedRow) {
        if  outlineView.isItemExpanded(clickedItem) {
            outlineView.animator().collapseItem(clickedItem)
        } else {
            outlineView.animator().expandItem(clickedItem, expandChildren: true)
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top