these damn trees are still WIP but I'm confident I'm doing everything right since I've recently embraced Stoicism
96 lines
2.6 KiB
Lua
96 lines
2.6 KiB
Lua
local Element = require "lib.simple_ui.core.element"
|
||
|
||
--- Объект, который отвечает за работу с элементами интерфейса одного экрана
|
||
--- @class UIBuilder
|
||
--- @field private _cache UIElement[]
|
||
--- @field elementTree UIElement
|
||
--- @field private shadowTree UIElement
|
||
local builder = {}
|
||
builder.__index = builder
|
||
|
||
--- @return UIBuilder
|
||
local function new(from)
|
||
from._cache = {}
|
||
from.shadowTree = Element:new {}
|
||
setmetatable(from, builder)
|
||
return from
|
||
end
|
||
|
||
-- --- @param element? UIElement
|
||
-- --- @private
|
||
-- function builder:_get(element)
|
||
-- if not element then return nil end
|
||
-- local key = builder:_makeKey(element)
|
||
-- if not key then return element end
|
||
|
||
-- local cached = self._cache[key]
|
||
-- if cached then return cached end
|
||
|
||
-- self._cache[key] = element
|
||
-- return element
|
||
-- end
|
||
|
||
--- @param newNode UIElement?
|
||
--- @param oldNode UIElement?
|
||
--- @private
|
||
function builder:didChange(newNode, oldNode)
|
||
if not oldNode or not newNode then
|
||
return true
|
||
end
|
||
if oldNode.type ~= newNode.type then return true end
|
||
if oldNode.key ~= newNode.key then return true end
|
||
return false
|
||
end
|
||
|
||
--- @param element UIElement
|
||
--- @private
|
||
function builder:_makeKey(element)
|
||
--if not element.key then return nil end
|
||
if type(element.key) == "string" then return element.key end
|
||
element.key = element.type .. "<" .. tostring(element.key) .. ">"
|
||
return element.key
|
||
end
|
||
|
||
--- @private
|
||
function builder:build_step(cur)
|
||
if cur.build then
|
||
local orphan = cur:build()
|
||
local child = cur.child
|
||
child = orphan
|
||
if not child then return end
|
||
|
||
child.parent = cur
|
||
cur.child = child
|
||
|
||
self:build_step(cur.child)
|
||
elseif cur.children then
|
||
for _, child in ipairs(cur.children) do
|
||
child.parent = cur
|
||
|
||
self:build_step(child)
|
||
end
|
||
end
|
||
end
|
||
|
||
--- Этот метод раскрывает всех отложенных (через build) детей в дереве и хитро их кэширует, чтобы не перестраивались постоянно
|
||
---
|
||
--- Благодаря этому можно каждый раз создавать новые элементы в верстке, а получать старые :)
|
||
function builder:build()
|
||
local root = self.elementTree
|
||
self:build_step(root)
|
||
end
|
||
|
||
function builder:layout()
|
||
self.elementTree:layout()
|
||
end
|
||
|
||
function builder:update(dt)
|
||
self.elementTree:update(dt)
|
||
end
|
||
|
||
function builder:draw()
|
||
self.elementTree:draw()
|
||
end
|
||
|
||
return new
|