Search code examples
objective-cmacoscocoansoutlineview

Expand NSOutlineView item on single click anywhere in row


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?


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.