CueText Color frustrations in Dark Mode

Others have mentioned it and I’m witnessing the same situation in my app - the macOS CueText color doesn’t work well with dark backgrounds in TextField or TextArea controls. It appears that the CueText color is relative to the control’s back color. This means that manually adjusting the control’s back color manually still doesn’t help since the CueText color changes to match the new back color.

It appears that showing or hiding a label based on the “GotFocus/LostFocus” events of the TextField/TextArea is the only way to accomplish a consistent CueText. This works on all three platforms. For example:

Sub GotFocus() tfSetNameCueText.Visible = False End Sub

Sub LostFocus() If Me.Text = "" Then tfSetNameCueText.Visible = True End If End Sub

We’re back to REALbasic 5 … Kind of makes the CueText property useless in non-default color themes.

Personally I prefer a separate label at the bottom of the Window anyway. Using MouseEnter and MouseExit the help text is shown instantly, does not obstruct anything, and doesn’t vanish before I read it.

Xojo’s not entirely to blame here, the CueText property or “placeHolder” uses an NSAttributedString. There is no actual property for setting the CueText color (that I’m aware of).

The following code uses ma huge azz library (which I can’t share right at this moment), but the code it’self should give you an idea of what’s needed to change the color of the CueText. Oh and the application will crash if you use this when there isn’t a CueText already set.

How to get the CueText color.

declare function getValue lib AppKit selector "placeholderTextColor" ( NSColorClass as integer ) as integer

How to set it on a TextField.

[code]Public Sub placeholderTextColor(extends inField as TextField, assigns inColor as color)
#if targetMacOS then
// — First we grab some settings from the TextField.
// We need to create a NSFont, so we’ll need the font name and font size.
// Sam Rowlands, Nov 2018

Dim fontName as string = inField.textFont
Dim fontSize as single = inField.textSize

if fontName = "SmallSystem" then // --- We want the smallSystem font.
  if fontSize = 0 then fontSize = NSFontSmallSystemFontSize( NSFontClass )
  fontName = "System"
elseif fontSize = 0 then
  fontSize = NSFontSystemFontSize( NSFontClass )
end if

// --- Now we can create a NSFont
Dim theFont as integer
if fontName = "System" or fontName = "" then
  theFont = NSFontSystemFontOfSize( NSFontClass, fontSize, NSFontWeight( NSFontWeightRegular ) )
  theFont = NSFontWithName( NSFontClass, fontName, fontSize )
end if

// --- Now we can create a NSColor
Dim theColor as integer = NSColor( inColor )

// --- We create an "string attributes" dictionary.
Dim attribs as integer = NSDictionaryWithObjectsForKeys( theFont : "NSFont", theColor : "NSColor" )

// --- We create an attributed string.
Dim attribString as integer = NSAttributedStringWithAttributes( inField.cueText, attribs )

// --- FInally we set that onto the text field.
declare sub setValue lib "AppKit" selector "setPlaceholderAttributedString:" ( NSTextFieldCellInstance as integer, NSAttributedStringInstance as integer )
setValue( NSCellFromNSControl( inField.handle ), attribString )

NSObjectRelease attribString

End Sub

Hope that this helps.

I popped that in, Sam, but my label method is actually more successful and works on all three platforms.

I understand your point, Markus. But the wizard that I’m working with doesn’t have a design permitting a “status bar” area. And, my mechanism works just like the CueText mechanism with next to no overhead.