Newer
Older
Radon / CardLayout.lua
--- Imports
local _ = require("util.score")
local sound = require("util.sound")
local eventHook = require("util.eventHook")
local renderHelpers = require("util.renderHelpers")

local Display = require("modules.display")

local Solyd = require("modules.solyd")
local hooks = require("modules.hooks")
local useCanvas = hooks.useCanvas

local Button = require("components.Button")
local SmolButton = require("components.SmolButton")
local BasicButton = require("components.BasicButton")
local BigText = require("components.BigText")
local bigFont = require("fonts.bigfont")
local SmolText = require("components.SmolText")
local smolFont = require("fonts.smolfont")
local BasicText = require("components.BasicText")
local Rect = require("components.Rect")
local RenderCanvas = require("components.RenderCanvas")
local Core = require("core.ShopState")
local Pricing = require("core.Pricing")
local ShopRunner = require("core.ShopRunner")
local ConfigValidator = require("core.ConfigValidator")

local loadRIF = require("modules.rif")

local function render(canvas, display, props, theme, version)
    local layoutName = theme.formatting.layoutFile
    local elements = {}

    local categories = renderHelpers.getCategories(props.shopState.products)
    local selectedCategory = props.shopState.selectedCategory
    local shopProducts = {}
    if categories[selectedCategory] then
        shopProducts = renderHelpers.getDisplayedProducts(categories[selectedCategory].products, props.configState.config.settings)
    end
    local currency = props.shopState.selectedCurrency

    local headerSuffix = ""
    if currency.name and currency.krypton and currency.krypton.currency then
        headerSuffix = "." .. currency.krypton.currency.name_suffix
    end
    local headerPadding = 2*6
    local headerWidth
    local headerText = currency.host or ""
    if currency.name then
        headerText = currency.name:gsub(headerSuffix .. "$", "")
        headerWidth = bigFont:getWidth(headerText)
    else
        headerWidth = bigFont:getWidth(headerText)
    end
    local headerStartX = 1
    local headerAlign = renderHelpers.getThemeSetting(theme, "formatting.headerAlign", layoutName)
    if  headerAlign == "center" then
        headerStartX = math.floor((display.bgCanvas.width - headerWidth) / 2)
    elseif headerAlign == "right" then
        headerStartX = display.bgCanvas.width - headerWidth - headerPadding - (#headerSuffix * 2)
    end
    local header = BigText {
        display = display,
        text = headerText,
        x = headerStartX,
        y = 3*2,
        align = "left",
        bg = renderHelpers.getThemeSetting(theme, "colors.bgColor", layoutName),
        color = renderHelpers.getThemeSetting(theme, "colors.headerColor", layoutName)
    }
    table.insert(elements, header)

    if headerSuffix and #headerSuffix > 0 then
        local suffix = BasicText {
            display = display,
            text = headerSuffix,
            x = math.floor((headerStartX + headerWidth + headerPadding)/2),
            y = 6,
            align = "left",
            bg = renderHelpers.getThemeSetting(theme, "colors.bgColor", layoutName),
            color = renderHelpers.getThemeSetting(theme, "colors.headerSuffixColor", layoutName)
        }
        table.insert(elements, suffix)
    end

    local subHeaderWidth = math.max( (display.bgCanvas.width / 2) / 2, #props.configState.config.branding.title)
    local subheaderStartX = 1
    if  headerAlign == "center" then
        subheaderStartX = math.floor(((display.bgCanvas.width / 2) - subHeaderWidth) / 2)
    elseif headerAlign == "right" then
        subheaderStartX = (display.bgCanvas.width/2) - subHeaderWidth
    end
    local subHeader = BasicText {
        display = display,
        text = props.configState.config.branding.title,
        x = subheaderStartX,
        y = 6 + 2,
        align = headerAlign,
        bg = renderHelpers.getThemeSetting(theme, "colors.subheaderBgColor", layoutName),
        color = renderHelpers.getThemeSetting(theme, "colors.subheaderColor", layoutName),
        width = subHeaderWidth
    }
    table.insert(elements, Rect {
        display = display,
        x = (subheaderStartX*2) - 1,
        y = ((6+2)*3) - 3,
        width = (subHeaderWidth*2) + 1,
        height = 4,
        color = renderHelpers.getThemeSetting(theme, "colors.subheaderBgColor", layoutName)
    })
    table.insert(elements, Rect {
        display = display,
        x = (subheaderStartX*2) - 2,
        y = ((6+2)*3) - 2,
        width = 1,
        height = 2,
        color = renderHelpers.getThemeSetting(theme, "colors.subheaderBgColor", layoutName)
    })
    table.insert(elements, Rect {
        display = display,
        x = ((subheaderStartX+subHeaderWidth)*2),
        y = ((6+2)*3) - 2,
        width = 1,
        height = 2,
        color = renderHelpers.getThemeSetting(theme, "colors.subheaderBgColor", layoutName)
    })
    table.insert(elements, subHeader)
    table.insert(elements, Rect {
        display = display,
        x = 5,
        y = 9*3,
        width = display.bgCanvas.width-10,
        height = 1,
        color = renderHelpers.getThemeSetting(theme, "colors.dividerColor", layoutName)
    })

    if renderHelpers.getThemeSetting(theme, "settings.showCredits", layoutName) then
        local credits = BasicText {
            display = display,
            text = "Radon",
            x = 1,
            y = 1,
            align = "left",
            bg = renderHelpers.getThemeSetting(theme, "colors.bgColor", layoutName),
            color = renderHelpers.getThemeSetting(theme, "colors.creditsColor", layoutName)
        }
        table.insert(elements, credits)
    end

    local cardX = (2*2) + 1
    local cardY = (10*3)+1
    local helperX = 1
    local currencySymbol = renderHelpers.getCurrencySymbol(currency, "small")
    local productBgColors = renderHelpers.getThemeSetting(theme, "colors.productBgColors", layoutName)
    local productBgShadowColors = renderHelpers.getThemeSetting(theme, "colors.productBgShadowColors", layoutName)

    for i = 1, #shopProducts do
        local product = shopProducts[i]
        local productAddr = product.address .. "@"
        if not props.shopState.selectedCurrency.name then
            productAddr = product.address
        end
        product.quantity = product.quantity or 0
        local qtyColor = renderHelpers.getThemeSetting(theme, "colors.normalQtyColor", layoutName)
        if product.quantity == 0 then
            qtyColor = renderHelpers.getThemeSetting(theme, "colors.outOfStockQtyColor", layoutName)
        elseif product.quantity < 10 then
            qtyColor = renderHelpers.getThemeSetting(theme, "colors.lowQtyColor", layoutName)
        elseif product.quantity < 64 then
            qtyColor = renderHelpers.getThemeSetting(theme, "colors.warningQtyColor", layoutName)
        end
        local productPrice = Pricing.getProductPrice(product, props.shopState.selectedCurrency)
        local priceString = tostring(productPrice) .. currencySymbol
        local productBgColor = productBgColors[((i-1) % #productBgColors) + 1]
        local productBgShadowColor = productBgShadowColors[((i-1) % #productBgShadowColors) + 1]
        local cardWidth = 2 + 2 + (math.max(
            #product.name,
            #(" Left: " .. tostring(product.quantity)),
            #(" Name: " .. productAddr),
            2+#priceString
        )*2)
        if cardWidth % 2 ~= 0 then
            cardWidth = cardWidth + 1
        end
        if cardX + cardWidth > display.bgCanvas.width then
            cardX = (2*2) + 1
            cardY = cardY + 8*3
        end

        -- Inner card
        table.insert(elements, Rect {
            display = display,
            x = cardX + 1,
            y = cardY + 4,
            width = cardWidth - 2,
            height = (6*3) - 2,
            color = productBgColor
        })
        -- Left border
        table.insert(elements, Rect {
            display = display,
            x = cardX,
            y = cardY + 5,
            width = 1,
            height = (5*3) - 1,
            color = productBgColor
        })
        -- Right Border
        table.insert(elements, Rect {
            display = display,
            x = cardX + cardWidth - 1,
            y = cardY + 5,
            width = 1,
            height = (5*3) - 1,
            color = productBgColor
        })
        -- Right shadow
        table.insert(elements, Rect {
            display = display,
            x = cardX + cardWidth,
            y = cardY + 6,
            width = 1,
            height = (5*3),
            color = productBgShadowColor
        })
        -- Bottom shadow
        table.insert(elements, Rect {
            display = display,
            x = cardX + 2,
            y = cardY + (6*3) + 2,
            width = cardWidth - 2,
            height = 1,
            color = productBgShadowColor
        })
        -- Bottom right shadow
        table.insert(elements, Rect {
            display = display,
            x = cardX + cardWidth - 1,
            y = cardY + (6*3) + 1,
            width = 1,
            height = 1,
            color = productBgShadowColor
        })
        -- Product name
        table.insert(elements, BasicText {
            display = display,
            text = product.name,
            x = math.floor((cardX/2) + 2),
            y = math.floor((cardY/3) + 3),
            align = "left",
            bg = productBgColor,
            color = renderHelpers.getThemeSetting(theme, "colors.productNameColor", layoutName)
        })
        -- Product quantity
        table.insert(elements, BasicText {
            display = display,
            text = " Left: ",
            x = math.floor((cardX/2) + 2),
            y = math.floor((cardY/3) + 4),
            align = "left",
            bg = productBgColor,
            color = renderHelpers.getThemeSetting(theme, "colors.fieldLabelColor", layoutName)
        })
        table.insert(elements, BasicText {
            display = display,
            text = tostring(product.quantity),
            x = math.floor((cardX/2) + 2) + #(" Left: "),
            y = math.floor((cardY/3) + 4),
            align = "left",
            bg = productBgColor,
            color = qtyColor
        })
        -- Product address (metaname)
        table.insert(elements, BasicText {
            display = display,
            text = " Name: ",
            x = math.floor((cardX/2) + 2),
            y = math.floor((cardY/3) + 5),
            align = "left",
            bg = productBgColor,
            color = renderHelpers.getThemeSetting(theme, "colors.fieldLabelColor", layoutName)
        })
        table.insert(elements, BasicText {
            display = display,
            text = productAddr,
            x = math.floor((cardX/2) + 2) + #(" Name: "),
            y = math.floor((cardY/3) + 5),
            align = "left",
            bg = productBgColor,
            color = renderHelpers.getThemeSetting(theme, "colors.addressColor", layoutName)
        })
        -- Product price
        table.insert(elements, BasicText {
            display = display,
            text = " " .. priceString .. " ",
            x = math.floor(((cardX + cardWidth)/2) - (#priceString + 2)),
            y = math.floor((cardY/3) + 6),
            align = "center",
            bg = renderHelpers.getThemeSetting(theme, "colors.priceBgColor", layoutName),
            color = renderHelpers.getThemeSetting(theme, "colors.priceColor", layoutName),
        })
        -- Product kristpay helper
        if props.shopState.selectedCurrency.name then
            local helperString = productAddr .. props.shopState.selectedCurrency.name
            table.insert(elements, BasicText {
                display = display,
                text = helperString,
                x = helperX,
                y = math.floor(cardY/3),
                align = "left",
                bg = renderHelpers.getThemeSetting(theme, "colors.bgColor", layoutName),
                color = renderHelpers.getThemeSetting(theme, "colors.bgColor", layoutName),
            })
            helperX = helperX + #helperString + 1
        end
        
        cardX = cardX + cardWidth + 4
    end

    -- Currencies
    if #props.configState.config.currencies > 1 then
        local currencyBgColors = renderHelpers.getThemeSetting(theme, "colors.currencyBgColors", layoutName)
        local maxCurrencyLeftX = math.floor( ((subheaderStartX*2) - 3) / 2)
        local minCurrencyRightX = math.ceil( (((subheaderStartX+subHeaderWidth)*2) + 3) / 2)
        local currencyX = 2
        for i = 1, #props.configState.config.currencies do
            local displayCurrency = props.configState.config.currencies[i]
            local displaySymbol = " " .. renderHelpers.getCurrencySymbol(displayCurrency, "small") .. " "
            local currencyBgColor = currencyBgColors[((i-1) % #currencyBgColors) + 1]
            if currencyX + #displaySymbol > maxCurrencyLeftX then
                currencyX = minCurrencyRightX
            end
            table.insert(elements, BasicButton {
                display = display,
                text = displaySymbol,
                x = currencyX,
                y = 6 + 2,
                align = "left",
                bg = currencyBgColor,
                color = renderHelpers.getThemeSetting(theme, "colors.currencyTextColor", layoutName),
                onClick = function()
                    props.shopState.selectedCurrency = props.configState.config.currencies[i]
                    props.shopState.lastTouched = os.epoch("utc")
                    if props.configState.config.settings.playSounds then
                        sound.playSound(props.peripherals.speaker, props.configState.config.sounds.button)
                    end
                end
            })
            currencyX = currencyX + #displaySymbol + 2
        end
    end

    -- Categories
    if #categories > 1 then
        local categoryBgColors = renderHelpers.getThemeSetting(theme, "colors.categoryBgColors", layoutName)
        local categoriesWidth = 0
        for i = 1, #categories do
            local category = categories[i]
            local categoryName = category.name
            if i == selectedCategory then
                categoryName = "[" .. categoryName .. "]"
            end
            categoriesWidth = categoriesWidth + #categoryName + 4
        end
        local categoryX = math.floor((display.bgCanvas.width / 4) - (categoriesWidth / 2))
        for i = 1, #categories do
            local category = categories[i]
            local categoryName = category.name
            local categoryBgColor = categoryBgColors[((i-1) % #categoryBgColors) + 1]
            if i == selectedCategory then
                categoryName = "[" .. categoryName .. "]"
                categoryBgColor = renderHelpers.getThemeSetting(theme, "colors.activeCategoryColor", layoutName)
            end
            table.insert(elements, BasicButton {
                display = display,
                text = " " .. categoryName .. " ",
                x = categoryX,
                y = math.floor(display.bgCanvas.height / 3) - 1,
                align = "left",
                bg = categoryBgColor,
                color = renderHelpers.getThemeSetting(theme, "colors.categoryTextColor", layoutName),
                onClick = function()
                    props.shopState.selectedCategory = i
                    props.shopState.lastTouched = os.epoch("utc")
                    if props.configState.config.settings.playSounds then
                        sound.playSound(props.peripherals.speaker, props.configState.config.sounds.button)
                    end
                end
            })
            categoryX = categoryX + #categoryName + 4
        end
    end

    if props.configState.config.settings.showFooter then
        local footerMessage
        if props.shopState.selectedCurrency.name or not props.configState.config.lang.footerNoName then
            footerMessage = props.configState.config.lang.footer
        else
            footerMessage = props.configState.config.lang.footerNoName
        end
        if props.shopState.selectedCurrency.name and footerMessage:find("%%name%%") then
            footerMessage = footerMessage:gsub("%%name%%", props.shopState.selectedCurrency.name)
        end
        if footerMessage:find("%%addr%%") then
            footerMessage = footerMessage:gsub("%%addr%%", props.shopState.selectedCurrency.host)
        end
        if footerMessage:find("%%version%%") then
            footerMessage = footerMessage:gsub("%%version%%", version)
        end

        if props.shopState.selectedCurrency then
            local footer = BasicText {
                display = display,
                text = footerMessage,
                x = 1,
                y = math.floor(display.bgCanvas.height / 3) ,
                align = renderHelpers.getThemeSetting(theme, "formatting.footerAlign", layoutName),
                bg = renderHelpers.getThemeSetting(theme, "colors.footerBgColor", layoutName),
                color = renderHelpers.getThemeSetting(theme, "colors.footerColor", layoutName),
                width = math.floor(display.bgCanvas.width / 2)
            }
            table.insert(elements, footer)
        end
    end

    return elements
end

return render