Converting picture for dark mode

I’m drawing a small image in a listbox, which I’d like to adapt for Dark Mode. I’m converting the picture to a template image and then retrieving the result. But the picture is unchanged in Dark Mode.

dim c as NSImageMBS = new NSImageMBS(myPicture)
c.isTemplate = true
myPicture = c.CopyPictureWithAlpha

What steps am I missing?

On iOS, I make sure the Alpha channel of the image has the image in it. I assume this is also the requirement on the Mac.

It does. The picture is rendered the same before and after conversion to-from an image (dark drawing with an alpha channel appropriate for light mode, rather than a white drawing).

In my experience NSImage.template only works when used with NSImage drawing or specifying functions. However you’ll also have problems with the ListBox as it’s a custom control (Not supplied by the OS) and in my tests, the results are all over the place for different versions of the macOS (which sadly is all too common with many API now).

If you are creating a sidebar of sorts, and you want the OS to manage the image for you, I would suggest looking into an alternative means of drawing the images, even using a canvas and [NSImage drawInRect].

Alternatively; if you really want to use a listbox, you can draw the NSImage into a Xojo picture, change it’s color to match [NSColor controlTextColor] or [NSColor labelColor] (I can’t recall which it is exactly), adjust the alpha slightly and draw it yourself.

@Sam Rowlands Thanks for the advice. What I don’t understand is how to automatically change the picture, a bitmapped grayscale graphic, from black (light mode) to white (dark mode). You say I should “change its color”, but how? I thought TintPictureMBS() might be useful here, but I haven’t been able to get it to work.

You can color a picture using the alpha channel with copymask and applymask.

A very simple example:

dim p2 as new Picture(p.Width,p.Height)        //width and height must match the original

p2.Graphics.forecolor=&cff0000        //fill the new picture with a color
p2.Graphics.FillRect(0,0,p2.Width,p2.Height)

p2.ApplyMask p.CopyMask        //apply the mask (alpha channel) of the original to the new picture

Thank you Jim, I think this may work. One glitch: the graphics are images in the project. p.CopyMask -> the Xojo error “CopyMask is not supported for images”.

For anyone else who might find this useful, here’s the solution I arrived at by modifying jim mckay’s example (with a helpful hint from Christian). In the listbox Paint event:

myImage = new NSImageMBS(myXojoImage)
myImage.setSize(32, 32) // works with retina and non-retina
dim p as picture = myImage.CopyPictureWithAlpha

dim p2 as new Picture(p.Width,p.Height)        //width and height must match the original
p2.Graphics.forecolor=&cFFFFFF       //fill the new picture with a color
p2.Graphics.FillRect(0,0,p2.Width,p2.Height)
p2.ApplyMask p.CopyMask        //apply the mask (alpha channel) of the original to the new picture

g.DrawPicture(p, 0, 2, 16, 16, 0, 0, myImage.Width, myImage.Height) //draw the image in