--- Объект, который отвечает за работу с элементами интерфейса одного экрана --- @class UIBuilder --- @field private _cache UIElement[] --- @field elementTree UIElement local builder = {} builder.__index = builder --- @return UIBuilder local function new(from) from._cache = {} 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 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 not cur then return end if cur.build then cur.child = self:_get(cur:build()) self:build_step(cur.child) elseif cur.children then for _, child in ipairs(cur.children) do self:build_step(self:_get(child)) end else cur.child = self:_get(cur.child) self:build_step(cur.child) end end --- Этот метод раскрывает всех отложенных (через build) детей в дереве и хитро их кэширует, чтобы не перестраивались постоянно --- --- Благодаря этому можно каждый раз создавать новые элементы в верстке, а получать старые :) function builder:build() local root = self:_get(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