See in class when Mojave switches between Light & Dark mode

I have several custom controls based on a canvas that I am updating for dark mode on Mojave. I’d like to have these controls (classes) be aware when Mojave switches between light and dark mode, to save calling each instance of this class from App.AppearanceChanged - basically to refresh/invalidate them so that they use new colours that have been set in App properties. Is there a way to do this?

Thanks in advance

Mark

You can loop over all windows in app.
Call a method on them to inform.

Either in window or in the event loop over all controls to call method on them.

An interface defined for controls interested could be helpful.

I’ve added a Feature Request for exactly those kind of situations…: <https://xojo.com/issue/53778>
It would be much more convenient than it is now :slight_smile:

Well… the Canvas-based Controls will get the .Paint Event fired after AppearanceChanged.
So you could add a private Property/Flag to your custom Canvas subclasses, and check if the current IsDarkMode value you get in the .Paint Event is the same as you’ve used in the last Paint-Event. If not - then something is different now :slight_smile:

Just again:

The .Paint event will get fired if the Appeareance (Dark/Light Mode) has changed. So basically you just need to check IsDarkMode in the Paint-Event and use the appropriate Colors. The above is just an idea if you want to know if it has changed - but that you only need to know if you for example have “dynamically cached Pictures” that you would need to rebuild then.

Thanks Christian and Jürg,

Both answer my question- I’ll work out which will be best and check out your Feedback Jürg.

Thanks

[quote] @Jürg Otter Well… the Canvas-based Controls will get the .Paint Event fired after AppearanceChanged.
So you could add a private Property/Flag to your custom Canvas subclasses, and check if the current IsDarkMode value you get in the .Paint Event is the same as you’ve used in the last Paint-Event. If not - then something is different now :)[/quote]

The only issue I see with this now that I’ve looked into it a bit more is that the user could change the Accent or Highlight colour in System Prefs which triggers AppearanceChanged, but if all you are doing in the Paint event handler is checking IsDarkMode then this change won’t get reflected in the UI. I might see if I can create a string version of the system appearance settings that can be stored and then compared each time a paint handler is called. Or that might be too much overhead in which case I’ll go with Christian’s suggestion.

Thanks anyway.

Then you could add additional private Color properties and see if IsDarkMode, TextColor or HighlightColor has changed…?
I’m not sure about the AccentColor - you might need a Declare to retrieve that…

And to add another idea… you could do this using a “Notification Center” and the Observer Pattern…
Xojo has two blog posts about that:
https://blog.xojo.com/2016/06/15/design-patterns-in-xojo-observer-part-1/
http://blog.xojo.com/2016/11/15/design-patterns-observer-part-ii/
You can’t take that example as-it-is - but you get the idea :wink:

And again: in most cases you don’t need to know if the Appearance has changed in a Canvas.Paint Event. If you’re then doing the drawing, it will pick up the “current” Colors. That’s really only required if you need to “destroy/rebuild” some cached ressources.

Oh, I’ve just had one more thought :slight_smile:
You could also just create a global property in a global module: AppearanceChangedCounter.
Increment it in App.AppearanceChanged, and have your Canvas.Paint's privately remember the “last used-for-painting counter value”. If the global one’s different - then Appearance has changed in between.

Hi Jürg, Yes I thought of the counter overnight too. Thanks for your replies.

I’ve thought about how to explain this in a way that doesnt sound condescending; I am not trying to be condescending, but I want to illustrate my experiences with things like this (and the Retina transition).

Ideally you want to be in place where you dont need to worry about what theme the user is using. Apple provide a whole bunch of color constants. They dont actually match the colors they use for building controls, but with some experimentation you should be able to find ones that are close enough for you to use.

Theres a couple of sample projects out there listing the various colors you can use.

In my experience with these things; the more complicated solutions you have to devise, the more you’re fighting the system and eventually you’ll lose, leading to even more frustration with Cooked Apple.