components_RadioDialog.bs

import "pkg:/source/utils/misc.bs"

sub init()
    m.contentArea = m.top.findNode("contentArea")
    m.radioOptions = m.top.findNode("radioOptions")
    m.scrollBarColumn = []

    m.top.observeField("contentData", "onContentDataChanged")
    m.top.observeFieldScoped("buttonSelected", "onButtonSelected")

    m.radioOptions.observeField("focusedChild", "onItemFocused")

    m.top.id = "OKDialog"
    m.top.height = 900
end sub

' Event handler for when user selected a button
sub onButtonSelected()
    if m.top.buttonSelected = 0
        m.global.sceneManager.returnData = m.top.contentData.data[m.radioOptions.selectedIndex]
    end if
end sub

' Event handler for when user's cursor highlights an option in the option list
sub onItemFocused()
    focusedChild = m.radioOptions.focusedChild
    if not isValid(focusedChild) then return

    moveScrollBar()

    ' If the option list is scrollable, move the option list to the user's section
    if m.scrollBarColumn.count() <> 0
        hightedButtonTranslation = m.radioOptions.focusedChild.translation
        m.radioOptions.translation = [m.radioOptions.translation[0], -1 * hightedButtonTranslation[1]]
    end if

end sub

' Move the popup's scroll bar
sub moveScrollBar()
    ' If we haven't found the scrollbar column node yet, try to find it now
    if m.scrollBarColumn.count() = 0
        scrollBar = findNodeBySubtype(m.contentArea, "StdDlgScrollbar")
        if scrollBar.count() = 0 or not isValid(scrollBar[0]) or not isValid(scrollBar[0].node)
            return
        end if

        m.scrollBarColumn = findNodeBySubtype(scrollBar[0].node, "Poster")
        if m.scrollBarColumn.count() = 0 or not isValid(m.scrollBarColumn[0]) or not isValid(m.scrollBarColumn[0].node)
            return
        end if

        m.scrollBarThumb = findNodeBySubtype(m.scrollBarColumn[0].node, "Poster")
        if m.scrollBarThumb.count() = 0 or not isValid(m.scrollBarThumb[0]) or not isValid(m.scrollBarThumb[0].node)
            return
        end if

        m.scrollBarThumb[0].node.blendColor = "#444444"
        ' If the user presses left then right, it's possible for us to lose focus. Ensure focus stays on the option list.
        scrollBar[0].node.observeField("focusedChild", "onScrollBarFocus")

        ' Hide the default scrollbar background
        m.scrollBarColumn[0].node.uri = ""

        ' Create a new scrollbar background so we can move the original nodes freely
        scrollbarBackground = createObject("roSGNode", "Rectangle")
        scrollbarBackground.color = "#101010"
        scrollbarBackground.opacity = "0.3"
        scrollbarBackground.width = "30"
        scrollbarBackground.height = m.contentArea.clippingRect.height
        scrollbarBackground.translation = [0, 0]
        scrollBar[0].node.insertChild(scrollbarBackground, 0)

        ' Determine the proper scroll amount for the scrollbar
        m.scrollAmount = (m.contentArea.clippingRect.height - int(m.scrollBarThumb[0].node.height)) / m.radioOptions.getChildCount()
        m.scrollAmount += m.scrollAmount / m.radioOptions.getChildCount()
    end if

    if not isvalid(m.radioOptions.focusedChild.id) then return

    m.scrollBarColumn[0].node.translation = [0, val(m.radioOptions.focusedChild.id) * m.scrollAmount]
end sub

' If somehow the scrollbar gains focus, set focus back to the option list
sub onScrollBarFocus()
    m.radioOptions.setFocus(true)

    ' Ensure scrollbar styles remain in an unfocused state
    m.scrollBarThumb[0].node.blendColor = "#353535"
end sub

' Once user selected an item, move cursor down to OK button
sub onItemSelected()
    buttonArea = findNodeBySubtype(m.top, "StdDlgButtonArea")

    if buttonArea.count() <> 0 and isValid(buttonArea[0]) and isValid(buttonArea[0].node)
        buttonArea[0].node.setFocus(true)
    end if
end sub

sub onContentDataChanged()
    i = 0
    for each item in m.top.contentData.data
        cardItem = m.radioOptions.CreateChild("StdDlgActionCardItem")
        cardItem.iconType = "radiobutton"
        cardItem.id = i

        if isValid(item.selected)
            m.radioOptions.selectedIndex = i
        end if

        textLine = cardItem.CreateChild("ScrollingLabel")
        textLine.maxWidth = "750"
        textLine.text = item.track.description
        cardItem.observeField("selected", "onItemSelected")
        i++
    end for
end sub

function onKeyEvent(key as string, press as boolean) as boolean
    if key = "right"
        ' By default RIGHT from the option list selects the OK button
        ' Instead, keep the user on the option list
        return true
    end if

    if not press then return false

    if key = "up"
        ' By default UP from the OK button is the scrollbar
        ' Instead, move the user to the option list
        if not m.radioOptions.isinFocusChain()
            m.radioOptions.setFocus(true)
            return true
        end if
    end if

    return false
end function