NSTableView: blue outline on right-clicked rows
Asked Answered
C

3

6

I'm wondering how I can get rid of the blue outlines that Cocoa draws around rows in NSTableView / NSOutlineView when right-clicking on them.

NSTableView Outline http://tobidobi.com/nstableview_outline.png

It doesn't seem to be a classic "highlight" nor a "focus ring" if I'm not mistaken - so, what is it, actually?

I'm currently drawing custom NSCells completely myself - but I can't figure out how to either
* draw this outline by myself, too, or
* get rid of it, or
* at least change its colour

Any hints are very welcome! Thanks!

Cupulate answered 18/11, 2010 at 21:28 Comment(0)
A
13

Unfortunately I'm not aware of any documented way to do this, short of writing your own table view replacement.

The method to override is:

- (void)drawContextMenuHighlightForRow:(NSInteger)row;

Please file an enhancement request with Apple so you won't have to rely on undocumented methods to do what you want in future. It looks like the other two table view highlight methods were made customizable in 10.6 but this one wasn't. I've always thought it was a bit clunky looking but it's necessary to indicate what row the menu is referencing (not necessarily the same as the highlighted row).

Anomie answered 19/11, 2010 at 3:33 Comment(3)
Thanks, I wasn't doing 64-bit Cocoa for a while there.Anomie
It is an undocumented API. Please tell weather it will pass the Mac App store review process?Dacey
No, typically this will not pass Mac App Store review. (I posted this answer prior to the existence of the Mac App Store, so it was not an issue then!)Anomie
A
2

My NSTableView *mainTableView is not sub-classed so I got rid of it just before the contextual menu opens:

- (void)menuWillOpen:(NSMenu *)menu{
     NSInteger rightClicked = [mainTableView clickedRow];
     [mainTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:rightClicked] byExtendingSelection:NO];
     [mainTableView deselectRow: rightClicked];
     [mainTableView reloadData];
    {
Askwith answered 26/12, 2015 at 3:32 Comment(1)
reloadData is unnecessary, but this is the way to go.Avi
P
0

Here is my attempt to re-draw these outlines:

import Cocoa

class TemplateOutlineView: NSOutlineView {
    
    private static let focusLineWidth: CGFloat = 2.0
    private static let focusLineColor = NSColor.controlAccentColor
    
    @objc
    func drawContextMenuHighlightForRow(_ row: Int) {
        guard !inLiveResize else { return }
        guard let ctx = NSGraphicsContext.current?.cgContext else { return }
        let rects = [CGRect](arrayLiteral: rect(ofRow: row))
        
        ctx.setLineWidth(TemplateOutlineView.focusLineWidth)
        ctx.setStrokeColor(TemplateOutlineView.focusLineColor.cgColor)
        
        let outerRect = bounds
            .insetBy(dx: 0.0, dy: 0.5)
            .offsetBy(dx: 0.0, dy: 0.5)
        for rect in rects.filter({ outerRect.intersects($0) }) {
            let innerRect = rect.intersection(outerRect)
            if innerRect.height > rect.height + 2.0 {
                ctx.addRect(innerRect
                                .insetBy(dx: TemplateOutlineView.focusLineWidth, dy: TemplateOutlineView.focusLineWidth + 0.5)
                                .offsetBy(dx: 0.0, dy: -0.5)
                )
            } else {
                ctx.addRect(rect
                                .insetBy(dx: TemplateOutlineView.focusLineWidth, dy: TemplateOutlineView.focusLineWidth + 0.5)
                                .offsetBy(dx: 0.0, dy: -0.5)
                )
            }
        }
        
        ctx.strokePath()
    }
    
}
Peraea answered 15/5, 2021 at 3:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.