1

I have NSButtons in a NSTableView, exactly as in my other question here.

I have implemented a switch between "Dark mode" and "Normal mode" using NSAppearance on the window in the NSWindowController:

override public func windowDidLoad() {
    if darkModeOn {
        setDarkMode()   
    } else {
        setLightMode()  
    }
}

func setDarkMode() {
    window?.appearance = NSAppearance(named: NSAppearanceNameVibrantDark)
    window?.backgroundColor = nil
}

func setLightMode() {
    window?.appearance = nil
    window?.backgroundColor = .white
}

The buttons have their isTemplate attribute to true, so that their color is the inverse of the window's one.

Light:

enter image description here

Dark:

enter image description here

This works ok when the app launches: the buttons are black when the window is white, and they're white when the window is dark.

But this doesn't work anymore when the app is already launched.

Once the app is launched, if I call setDarkMode() when the window is white, I suddenly get black or grey buttons instead of the desired white ones.

enter image description here

Same if I call setLightMode() when the window is dark.

enter image description here

In both cases, the buttons return to normal once I scroll the tableView back and forth enough to force the cells to be redrawn.

Note another side-effect of switching the window's state: some of the the tableView's row separators are suddenly thicker, and also become normal again after the scrolling.

As you can imagine, I don't want the user to be forced to quit the app and relaunch, so I would like to have all these things correctly drawn in the window when the NSAppearance changes.

Unfortunately I've tried many solutions without success: combinations of needsDisplay and other ways to force "refreshing" the buttons (and the tableView row separators) have had no effect whatsoever. The documentation is sparse. I've watched all WWDC videos. I'm lost. :p

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
  • I may be wrong, but I didn't think this was designed to be changed at runtime and appearance changes like these require the application to be restarted. – Joshua Nozzi May 24 '17 at 20:54
  • @JoshuaNozzi Yeah that's what I feared. I will research different approaches - still hoping that someone could find a trick to make this simple way work, though. :p – Eric Aya May 24 '17 at 21:29
  • Hey @Moritz, I think you could redraw the rows with `reloadRowsAtIndexPaths:withRowAnimation:` or maybe even better solution is to hide and show the whole `NSTableView` again :-) the first is kinda nice solution the second is a real FORCE redraw :P. Hide for 1 frame and draw it again (A blink for 1 frame is better than forcing user to restart the app). – Coldsteel48 Feb 09 '18 at 02:09
  • I think the reason you are hitting this issue is because NSTableView is set to reuse the cells. Thus it just doesn't draw them once they are visible, you could try to set the cells not to reuse and see if the problem still exists. Ofcourse not reusing them has some performance tolls, but it is up to your needs - I bet macs can handle it well (iPhone4 did well in my experience couple of years ago, and the `UITableView` was quite sophisticated). – Coldsteel48 Feb 09 '18 at 02:12
  • Maybe a simplest way to be to override the didLayout() method and change the TableView's frame to another value - this should redraw the whole thing and in the next frame return it to the needed frame (like in a blurry text question). – Coldsteel48 Feb 09 '18 at 02:20

0 Answers0