Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom selection style for view based "Source List" NSOutlineView

I'm using a view based NSOutlineView that has it's selectionHighlightStyle set to NSTableViewSelectionHighlightStyleSourceList.

I want to overwrite the selection style (background) for certain rows and draw a different color/gradient.

What I tried so far is creating a custom NSTableRowView and returning it via outlineView:rowViewForItem:. I verified that my custom row views are created and returned by the outline view delegate. However, none of the methods I'm overwriting in the custom row view are being called.

I tried to overwrite drawBackgroundInRect:, drawSelectionInRect:, drawSeparatorInRect: and even drawRect:. None of those are called, ever.

I'm suspecting the outline view to be doing some custom "magic" when it's set to the source list style, but I've not found anything in the documentation that indicates that a custom NSTableRowView wouldn't be honored at all in this case.

like image 866
lemonmojo Avatar asked Dec 03 '25 17:12

lemonmojo


2 Answers

AppKit adds separate NSVisualEffectView with custom material to row view for drawing background when using NSTableViewSelectionHighlightStyleSourceList. I've come up with the following workaround which uses zero private APIs, but can break later if Apple implements some other way of highlighting rows.

@class CustomHighlightRowSelectionView;
@interface CustomHighlightRowView : NSTableRowView

@property (nonatomic, strong) CustomHighlightRowSelectionView *selectionView;

@end

@interface CustomHighlightRowSelectionView : NSView

@property (nonatomic, getter=isEmphasized) BOOL emphasized;
@property (nonatomic, getter=isSelected) BOOL selected;

@end


@implementation CustomHighlightRowView

- (CustomHighlightRowSelectionView *)selectionView
{
    if (!_selectionView)
    {
        _selectionView = [[CustomHighlightRowSelectionView alloc] initWithFrame:NSZeroRect];
    }

    return _selectionView;
}

- (void)setEmphasized:(BOOL)emphasized
{
    [super setEmphasized:emphasized];
    self.selectionView.emphasized = emphasized;
}

- (void)setSelected:(BOOL)selected
{
    [super setSelected:selected];
    self.selectionView.selected = selected;
}

- (void)addSubview:(NSView *)aView positioned:(NSWindowOrderingMode)place relativeTo:(NSView *)otherView
{
    if (![aView isKindOfClass:[NSVisualEffectView class]])
    {
        [super addSubview:aView positioned:place relativeTo:otherView];
    }
    else
    {
        if (!self.selectionView.superview)
        {
            [super addSubview:self.selectionView positioned:place relativeTo:otherView];
            self.selectionView.frame = self.bounds;
        }
    }
}

- (void)setFrame:(NSRect)frame
{
    [super setFrame:frame];

    self.selectionView.frame = self.bounds;
}

- (void)setBounds:(NSRect)bounds
{
    [super setBounds:bounds];

    self.selectionView.frame = self.bounds;
}

@end

@implementation CustomHighlightRowSelectionView

- (void)setEmphasized:(BOOL)emphasized
{
    _emphasized = emphasized;
    [self setNeedsDisplay:YES];
}

- (void)setSelected:(BOOL)selected
{
    _selected = selected;
    [self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)dirtyRect
{
    if (!self.selected)
    {
        return;
    }

    NSColor *fillColor = self.emphasized ? [NSColor alternateSelectedControlColor] : [NSColor secondarySelectedControlColor];
    [fillColor setFill];
    NSRectFill(dirtyRect);
}

@end
like image 107
Denys Stas Avatar answered Dec 06 '25 06:12

Denys Stas


Are you using Yosemite? From Apple's document Adopting Advanced Features of the new UI in Yosemite

When selectionHighlightStyle == NSTableViewSelectionHighlightStyleSourceList • Selection is now a special blue material that does behind window blending - The material size and drawing can not be customized

If you set it to NSTableViewSelectionHighlightStyleRegular and override the drawRect, it should work.

like image 22
Oskar Avatar answered Dec 06 '25 07:12

Oskar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!