components_ui_button_TextButton.bs
import "pkg:/source/utils/misc.bs"
sub init()
m.buttonFocusBorder = m.top.findNode("buttonFocusBorder")
m.buttonBackground = m.top.findNode("buttonBackground")
m.buttonText = m.top.findNode("buttonText")
m.top.observeField("background", "onBackgroundChanged")
m.top.observeField("textColor", "onTextColorChanged")
m.top.observeField("text", "onTextChanged")
m.top.observeField("padding", "onPaddingChanged")
m.top.observeField("focusedChild", "onFocusChanged")
m.top.observeField("minWidth", "onSizeChanged")
m.top.observeField("minHeight", "onSizeChanged")
applyTheme()
end sub
sub applyTheme()
colorConstants = m.global.constants.colors
' Set default colors
m.top.background = colorConstants.background_secondary
m.top.textColor = colorConstants.text_primary
m.top.focusBackground = colorConstants.background_primary
m.top.textFocusColor = colorConstants.text_primary
end sub
sub onFocusChanged()
colorConstants = m.global.constants.colors
if m.top.hasFocus()
' Button background
if isValid(m.top.focusBackground)
m.buttonBackground.blendColor = m.top.focusBackground
end if
' Button text
if isValid(m.top.textFocusColor)
m.buttonText.color = m.top.textFocusColor
end if
' Focus border
if m.top.enableBorder
m.buttonFocusBorder.blendColor = colorConstants.primary
m.buttonFocusBorder.visible = true
end if
else
' Button background
if isValid(m.top.background)
m.buttonBackground.blendColor = m.top.background
end if
' Button text
if isValid(m.top.textColor)
m.buttonText.color = m.top.textColor
end if
' Focus border
m.buttonFocusBorder.visible = false
end if
end sub
sub onBackgroundChanged()
m.buttonBackground.blendColor = m.top.background
end sub
sub onTextColorChanged()
m.buttonText.color = m.top.textColor
end sub
sub onTextChanged()
m.buttonText.text = m.top.text
setSizeAndCenterText()
end sub
sub setSizeAndCenterText()
if not isValid(m.buttonText) then return
if m.buttonText.text.Len() = 0 then return
' Store the current text to detect if we've already sized for this text
if not isValid(m.lastSizedText) then m.lastSizedText = ""
if m.lastSizedText = m.buttonText.text and isValid(m.top.width) and m.top.width > 0
' We've already sized this text, just update the focus border and return
setFocusBorderSize()
return
end if
m.lastSizedText = m.buttonText.text
' Always use font-based calculation to avoid stale localBoundingRect() issues
textLength = m.buttonText.text.Len()
fontSize = m.buttonText.font.size
charWidth = fontSize * 0.64
textWidth = textLength * charWidth
' Use font size for height to avoid stale localBoundingRect() issues
textHeight = fontSize
' print "[TextButton] text='"; m.buttonText.text; "', length="; textLength; ", charWidth="; charWidth; ", textWidth="; textWidth; ", textHeight="; textHeight
' Calculate button dimensions with padding
buttonWidth = textWidth + (m.top.padding * 2)
buttonHeight = textHeight + (m.top.padding * 2)
' print "[TextButton] size with padding: width=", buttonWidth, ", height=", buttonHeight
' Ensure minimum dimensions (this is the ONLY place minWidth should be enforced)
if buttonWidth < m.top.minWidth
buttonWidth = m.top.minWidth
end if
if buttonHeight < m.top.minHeight
buttonHeight = m.top.minHeight
end if
' print "[TextButton] ACTUAL size (using minWidth): width=", buttonWidth, ", height=", buttonHeight
' Set background size
m.buttonBackground.width = buttonWidth
m.buttonBackground.height = buttonHeight
' Center the text in the button
m.buttonText.width = buttonWidth
m.buttonText.height = buttonHeight
m.buttonText.translation = [0, 0]
setFocusBorderSize()
end sub
sub onPaddingChanged()
setSizeAndCenterText()
end sub
sub onSizeChanged()
setSizeAndCenterText()
end sub
sub onHeightChanged()
setSizeAndCenterText()
end sub
sub onWidthChanged()
setSizeAndCenterText()
end sub
sub onEnabledChanged()
colorConstants = m.global.constants.colors
if m.top.enabled
m.top.background = colorConstants.background_secondary
m.top.textColor = colorConstants.text_primary
else
m.top.background = colorConstants.background_primary
m.top.textColor = colorConstants.text_disabled
end if
end sub
sub setFocusBorderSize()
if not m.top.enableBorder then return
if m.buttonBackground.width < 1 then return
m.buttonFocusBorder.width = m.buttonBackground.width + (m.top.borderSize * 2)
m.buttonFocusBorder.height = m.buttonBackground.height + (m.top.borderSize * 2)
' translate the button so the focus border is visible
m.buttonBackground.translation = [m.top.borderSize, m.top.borderSize]
m.buttonText.translation = [m.top.borderSize, m.top.borderSize]
end sub