Search code examples
applescript-objc

How to change the selection color of a sidebar?


Is there any way to change the selection color of a sidebar item? For example the default color of macOS 10.14.x dark theme is blue, would it be possible to change this color? I took a look here: Cocoa osx NSTableview change row highlight color but I had difficulty translating to Applescript, thanks in advance. enter image description here


Solution

  • Without a sample or MCVE project it is going to be tricky providing a drop-in solution. The topics and answers you linked to are overriding the NSTableView or NSTableRowView classes, so I can give you a generic solution for that. Subclassing in AppleScriptObjC can be a bit of a pain, depending on what you need to reference, but is fairly straightforward. Essentially you are putting a custom class in between the regular class and your application, where you can intercept the various standard method calls.

    For a cell-based table view example, add a new empty file to your project by using the File > New > File... menu item. The name of the _file _isn't important (e.g. TableViewHighlight.applescript or whatever), the name of the script is what will be used by Xcode. Here I am using MyTableView for the class name and referencing a tableView outlet property from the AppDelegate:

    script MyTableView -- the name of your custom class
    
        property parent : class "NSTableView" -- the parent class to override
        property tableView : a reference to current application's NSApp's delegate's tableView
        property highlightColor : a reference to current application's NSColor's greenColor -- whatever
    
        # set the row highlight color
        on drawRow:row clipRect:clipRect
            if tableView's selectedRowIndexes's containsIndex:row then -- filter as desired
                highlightColor's setFill()
                current application's NSRectFill(tableView's rectOfRow:row)
            end if
            continue drawRow:row clipRect:clipRect -- super
        end drawRow:clipRect:
    
        # set the highlight color of stuff behind the row (grid lines, etc)
        on drawBackgroundInClipRect:clipRect
            highlightColor's setFill()
            current application's NSRectFill(clipRect)
            continue drawBackgroundInClipRect:clipRect -- super
        end drawBackgroundInClipRect:
    
    end script
    

    In the Interface Editor, use the Identity Inspector to set the class of your table view to the MyTableView class. Finally, in your table view setup set its highlighting to none, since it will be done by your subclass (again, assuming a tableView outlet is connected to the table view):

        tableView's setSelectionHighlightStyle: current application's NSTableViewSelectionHighlightStyleNone
    

    For a view-based table view example, the process is similar, but NSTableRowView is the one to subclass. Here the name of the script/class I am using will be MyTableRowView:

    script MyTableRowView -- the name of your custom class
    
        property parent : class "NSTableRowView" -- the parent class to override
        property highlightColor : a reference to current application's NSColor's redColor -- whatever
    
        # draw the selected row
        on drawSelectionInRect:dirtyRect
            continue drawSelectionInRect:dirtyRect
            highlightColor's setFill()
            current application's NSRectFill(dirtyRect)
        end drawSelectionInRect:
    
    end script
    

    In the Interface Editor, set the table view's highlight to regular using the Attributes Inspector, and add a tableView:rowViewForRow: method to the table view's delegate:

    on tableView:tableView rowViewForRow:row
        set rowIdentifier to "MyTableRow"
        set myRowView to tableView's makeViewWithIdentifier:rowIdentifier owner:me
        if myRowView is missing value then
            set myRowView to current application's MyTableRowView's alloc's initWithFrame:current application's NSZeroRect
            myRowView's setIdentifier:rowIdentifier
        end if
        return myRowView
    end tableView:rowViewForRow:
    

    There are other options, of course, but that should get you started, and help with translating some of those Objective-C answers/examples.