local Element = require "lib.simple_ui.core.element" --- Объект, который отвечает за работу с элементами интерфейса одного экрана --- @class UIBuilder --- @field builder fun(): UIElement --- @field private elementTree UIElement local builder = {} builder.__index = builder --- @return UIBuilder local function new(from) setmetatable(from, builder) return from 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 return element.type .. "<" .. tostring(element.key) .. ">" end --- @param cur UIElement --- @private function builder:build_step(cur) -- Самоприсваивания должны вырезаться компилятором, я в это верю cur = cur --[[@as SingleChildElement | MultiChildElement]] local buildRes = cur:build() if not buildRes then return end if buildRes.type then cur = cur --[[@as SingleChildElement]] cur._child_ = buildRes buildRes._parent_ = cur self:build_step(cur._child_) else cur = cur --[[@as MultiChildElement]] cur._children_ = buildRes for _, child in ipairs(cur._children_) do child._parent_ = cur self:build_step(child) end end end --- Этот метод раскрывает всех отложенных (через build) детей в дереве и хитро их кэширует, чтобы не перестраивались постоянно --- --- Благодаря этому можно каждый раз создавать новые элементы в верстке, а получать старые :) function builder:build() self.elementTree = self:builder() self:build_step(self.elementTree) 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