I’ve spent several days, first attempting to do the alignment with native Xojo (and a picture/graphics) and still couldn’t get it right.
Yesterday after spelunking, I found the macOS API that I needed (which of course isn’t exposed by Xojo). So I present to you the code I’ve created to be able to align an imagewell control array and a label control array.
// --- Now align the label control array and the imagewell control array.
const maxIconWidth as integer = 16
const iconPlusPadding as integer = 20
Dim rowTop as double = 100
Dim rowMinHeight as double = 24
Dim textTopOffset, textHeight, labelVPadding as double
Dim textFont as integer
Dim contentSize as NSSize
For l as integer = 0 to lastAddedRowIndex
// --- Vertically center a Xojo Label or NSTextField.
// 1. This works by obtaining the "baseline", then calulating the textTopOffset and the textHeight
// from the label's typeface. We then center on the text height, and use the offset to shift
// the label/field up.
// 2. Xojo doesn't support floats for control placement, so we MUST round the font attribue values.
textFont = NSTextField_font( stLabel( l ).handle )
textTopOffset = NSView_firstBaselineOffsetFromTop( stLabel( l ).handle ) - round( NSFont_ascender( textFont ) )
textHeight = ( NSView_firstBaselineOffsetFromTop( stLabel( l ).handle ) - round( NSFont_descender( textFont ) ) ) - textTopOffset
labelVPadding = ( ( rowMinHeight - textHeight ) / 2.0 ) - textTopOffset
stLabel( l ).top = labelVPadding + rowTop
// --- Now we can set the height of the field, we'll just ask the macOS for that.
contentSize.width = stLabel( l ).width // --- Must be reset each time we use it.
contentSize.height = 3000 // --- we set this to the max value we can think of.
contentSize = NSControl_sizeThatFits( stLabel( l ).handle, contentSize ) // --- This little gem, gives us the text size!
stLabel( l ).height = contentSize.height
// --- Now align the SF Symbols.
// 1. SF Symbols can be really weird sizes, not just odd numbers, but even half numbers. Xojo uses
// integers only, so we have to size the imagewell to a multiple of 2.
// 2. Once we have the height of the imagewell, we can then center that based upon the matching
// text rendering measurements we got while centering the label/field.
icon = NSImageView_image( stIcon( l ).handle )
stIcon( l ).width = ceil( ceil( NSImage_size( icon ).width ) / 2.0 ) * 2.0
stIcon( l ).height = ceil( ceil( NSImage_size( icon ).height ) / 2.0 ) * 2.0
stIcon( l ).left = ( ( maxIconWidth - stIcon( l ).width ) / 2.0 ) + ( stLabel( l ).left - iconPlusPadding )
sticon( l ).top = ( ( textHeight - stIcon( l ).height ) / 2.0 ) + ( stLabel( l ).top + textTopOffset )
// --- incredment the row height, by either the miniumRowHeight or if the text is too great, but that and the padding.
rowTop = rowTop + max( rowMinHeight, stLabel( l ).height + ( labelVPadding * 2.0 ) )
next