Native looking macOS preferences toolbar

I am trying to create a native looking macOS preferences toolbar in Xojo, like the one used in Safari, for example (let’s ignore the lack of Retina just now):

I am using PNG files as icons (for now), overlaying the current accent color on them, setting the NSWindowMBS.toolbarStyle to 2 and calling Pressed to force the toolbar buttons to work as radio buttons.

Here is the sample project (API 2, because why not :slight_smile: ), and while it works more or less fine, it still does not have the native look & feel. For example, when I hoover the pointer over a selected icon, the caption changes color, but the icon itself does not. This is how it looks in Safari (and Xojo IDE, so it is possible to achieve):

test-01

How can I change the icon color under the pointer? And how can I know what color should be used? Is there some declare magic (or MBS call) to make the icon change color automatically? If not, how can I detect when the pointer is over a toolbar icon?

Also, what should I do about the dark mode? The accent color I am overlaying on the icons, that is, ColorGroup.NamedColor(“controlAccentColor”), seems to be the same regardless of dark/light mode setting, but in the dark mode the preferences icons should have a different color. How can I get the correct dark accent color to overlay?

You should not colorize the icons yourself, and instead let the OS deal with it for you.

  1. Use declares or MBS to load your images as a NSImage.
    Dim myicon as ptr = NSImage_withName( "myimage" )

  2. Use declares or MBS to set the “Template” property on the NSImage.
    NSImage_setTemplate( myIcon ) = true

  3. Use declares or MBS to set the toolbar item’s icon to your NSImage.
    NSToolbarItem_setImage( myToolbarItem.handle ) = myIcon

Note: Code was just typed and not checked in anyway possible, but should work with the Ohanaware App Kit.

Edit: Typos…

3 Likes

See also
NSImageMBS.imageNamed(name as string) as NSImageMBS
NSImageMBS.isTemplate as Boolean

like this:

Dim ActionGearTemplate as string // content of PDF file
Dim Image as New NSImageMBS( ActionGearTemplate )
Image.setSize( 14,14 )
Image.IsTemplate = true

in MBS Xojo Plugins.

1 Like

OK, so now I am doing it like this:

var icon1 As NSImageMBS = NSImageMBS.imageWithSystemSymbolName("gearshape")
var icon2 As NSImageMBS = NSImageMBS.imageWithSystemSymbolName("heart.text.square")

if icon1<>nil and icon2<>nil then
  
  icon1.setSize(50,50) // BTW how can I know the proper size of each icon?
  icon2.setSize(50,40)
  
  icon1.isTemplate=true
  icon2.isTemplate=true
  
  var myButton1 As New DesktopToolbarButton
  var myButton2 As New DesktopToolbarButton
  
  myButton1.Caption = "General"
  myButton1.Icon = icon1.CopyPictureWithAlpha
  myButton1.ButtonStyle=DesktopToolbarButton.ButtonStyles.ToggleButton
  myButton1.Tag=1
  
  myButton2.Caption = "Test"
  myButton2.Icon = icon2.CopyPictureWithAlpha
  myButton2.ButtonStyle=DesktopToolbarButton.ButtonStyles.ToggleButton
  myButton2.Tag=2
  
  me.AddButton myButton1
  me.AddButton myButton2
  
end if

But I still have to overlay the accent color myself (in myToolbarPREF.Pressed), so that the icon changes color when clicked. Without that, only the caption color changes.

I guess I am assigning the icon improperly? CopyPictureWithAlpha generates a simple Picture from NSImage, so it isn’t really different from using a picture from Xojo imageset, right?

Because you are getting to the very last step and then converting the NSImage to a Xojo Picture. When you do this it loses the template property as Xojo pictures have no concept “template”.

You also shouldn’t need to set the image size as the NSToolbarItem should auto resize the icon.

Perhaps a Feedback request to be able to set template when Xojo sets your images to controls is in order.

Lastly; I’d recommend getting a copy of Aqua Swatch from the Mac App Store. This will allow you to browse a list of known NSImage constants, which are auto mapped to SF Symbols on Big Sur and above, yet still work on older versions of the macOS.

2 Likes

It would also be good if Xojo themselves could share how they made the preferences window. If it was made in a different tool, it should be re-written in Xojo and for Xojo to expose the functions that they needed to make it platform consistent.

It would not only improve the Xojo framework, but help Xojo’s customers to create better x-plat apps.

2 Likes

Thanks! I’ve got it now!

var n1 As NSImageMBS = NSImageMBS.imageWithSystemSymbolName("gearshape")
var n2 As NSImageMBS = NSImageMBS.imageWithSystemSymbolName("heart.text.square")

if n1<>nil and n2<>nil then
  
  n1.isTemplate=true
  n2.isTemplate=true
  
  var its() as NSToolbarItemMBS
  its=self.NSToolbarMBS.items
  its(0).Image=n1
  its(1).Image=n2
  
end if

I’m putting a sample project to download here in case anyone finds it useful (API 2, MBS plugins required).

3 Likes

In case someone would like a “Declare” version, the code is included as part of my Ohanaware App Kit App Kit 2021 - Building Better Mac Applications

Aqua Swatch will help you find NSImageNames that will give you SF-Symbols on Big Sur or above, while providing icons for older versions. Aqua Swatch

1 Like

Thanks for sharing.

We used a bunch of declares to do this, as well as creating a few symbols of our own in SVG which were compressed into an asset catalog.

1 Like

Thank you for sharing this information @Greg_O_Lone

I think it would be really be helpful to the community and to Xojo as a x-plat tool, if the steps that are required, are digested and then integrated into Xojo.

While I could log Feedback cases for this particular process, I am sure that there are others areas where Xojo has already put in the work to do a process correctly and Xojo’s customers are left to figure it out for themselves, often stumbling along the way, like @Grzegorz_Pawlik, who tried so hard that they ended up colorizing the icons themselves, when it totally wasn’t needed.

For instance:

  1. Add a option to the toolbar class that allows for specification of “Toolbar” style.
  2. Add a options property to the Xojo picture class, that would allow for the value of “Template” to be set (potentially others, down the road, i.e. meta data).
  3. Allow the IDE to accept SVG files as pictures, on application build, do what is needed to make it “work” on each platform.

Then create a blog article or include with the language reference on how to get a platform consistent “Preferences” toolbar, by simply…

I realize that this means more work for the existing team, perhaps it really is time to hire a few more peeps in the engineering team.

3 Likes

var n1 As NSImageMBS = NSImageMBS.imageWithSystemSymbolName(“gearshape”) doesn’t work on Catalina but ok I assume on Monterey. What would the issue be?

Maybe the name got introduced in the newer version?

I tried a few options including “heart.text.square” which seems to work on the second line?? Where do I get a list of acceptable names?

var n1 As NSImageMBS = NSImageMBS.imageWithSystemSymbolName(“multiply.circle.fill”)
var n2 As NSImageMBS = NSImageMBS.imageWithSystemSymbolName(“heart.text.square”)

take that back neither line works on catalina

SFSymbols have been introduced with macOS 11. So I’m not surprised that you don’t get any images displayed under Catalina.

1 Like

SF Symbols require macOS 10.16 Big Sur.

You can use Aqua Swatch to browse system images that are available from 10.0 to 12.0

Alternatively, you can use App Wrapper to rasterize SF Symbols (has to be done on Big Sur or newer), to which are then included in the resources of your application, when wrapped.

1 Like

Thanks Sam

1 Like

I totally forgot that I’ve made some improvements to the SF Symbol rasterizer for App Wrapper 4.4!

Not out yet right?

Available from here for the moment. App Wrapper 4 - Prereleases