diff --git a/lib/simple_ui/core/builder.lua b/lib/simple_ui/core/builder.lua index 643fd8b..245cf23 100644 --- a/lib/simple_ui/core/builder.lua +++ b/lib/simple_ui/core/builder.lua @@ -2,34 +2,17 @@ local Element = require "lib.simple_ui.core.element" --- Объект, который отвечает за работу с элементами интерфейса одного экрана --- @class UIBuilder ---- @field private _cache UIElement[] ---- @field elementTree UIElement ---- @field private shadowTree UIElement +--- @field builder fun(): UIElement +--- @field private elementTree 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 @@ -44,37 +27,30 @@ 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 +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]] - if cur.build then + local buildRes = cur:build() + if not buildRes then return end + + if buildRes.type then cur = cur --[[@as SingleChildElement]] - local child = cur:build() - if not child then return end - - -- local oldChild = cur._child_ - -- if oldChild then - -- for key, value in pairs(oldChild) do - -- if (not Element[key]) then child[key] = value end - -- end - -- end - - cur._child_ = child - child._parent_ = cur + cur._child_ = buildRes + buildRes._parent_ = cur self:build_step(cur._child_) - elseif cur.children then + else cur = cur --[[@as MultiChildElement]] - for _, child in ipairs(cur.children) do + cur._children_ = buildRes + for _, child in ipairs(cur._children_) do child._parent_ = cur self:build_step(child) end @@ -85,8 +61,8 @@ end --- --- Благодаря этому можно каждый раз создавать новые элементы в верстке, а получать старые :) function builder:build() - local root = self.elementTree - self:build_step(root) + self.elementTree = self:builder() + self:build_step(self.elementTree) end function builder:layout() diff --git a/lib/simple_ui/core/multi_child_element.lua b/lib/simple_ui/core/multi_child_element.lua index a4da47a..2e635be 100644 --- a/lib/simple_ui/core/multi_child_element.lua +++ b/lib/simple_ui/core/multi_child_element.lua @@ -2,12 +2,18 @@ local Element = require "lib.simple_ui.core.element" --- @class MultiChildElement : UIElement --- @field children UIElement[] +--- @field _children_ UIElement[] local element = setmetatable({}, require "lib.simple_ui.core.element") element.__index = element -element.children = {} +element._children_ = {} + +--- @return UIElement[] +function element:build() + return self.children +end function element:update(dt) - for _, child in ipairs(self.children) do + for _, child in ipairs(self._children_) do child:update(dt) end end @@ -15,19 +21,19 @@ end function element:draw() love.graphics.push("transform") love.graphics.translate(self._offset_.x, self._offset_.y) - for _, child in ipairs(self.children) do + for _, child in ipairs(self._children_) do child:draw() end --- @TODO: сделать дебажный метод для отрисовки границ love.graphics.setColor(1, 0, 0) - love.graphics.line(0, 0, 0 + self._size_.x, 0) - love.graphics.line(0, 0, 0, self._offset_.y + 0) - love.graphics.line(0 + self._size_.x, self._offset_.y, 0 + self._size_.x, - 0 + self._size_.y) - love.graphics.line(0, 0 + self._size_.y, 0 + self._size_.x, - 0 + self._size_.y) + love.graphics.line(0, 0, self._size_.x, 0) + love.graphics.line(0, 0, 0, self._size_.y) + love.graphics.line(self._size_.x, 0, self._size_.x, + self._size_.y) + love.graphics.line(0, self._size_.y, self._size_.x, + self._size_.y) love.graphics.setColor(1, 1, 1) love.graphics.pop() diff --git a/lib/simple_ui/elements/flex.lua b/lib/simple_ui/elements/flex.lua index c98cd09..9384732 100644 --- a/lib/simple_ui/elements/flex.lua +++ b/lib/simple_ui/elements/flex.lua @@ -16,7 +16,7 @@ function element:layout() local mainAxisSize = 0 local crossAxisSize = 0 if self.direction == "horizontal" then - for _, child in ipairs(self.children) do + for _, child in ipairs(self._children_) do child._constraints_ = Constraints { maxHeight = self._constraints_.maxHeight } child:layout() if child._size_.y > crossAxisSize then crossAxisSize = child._size_.y end @@ -30,7 +30,7 @@ function element:layout() start = self._constraints_.maxWidth - mainAxisSize end local shift = 0 - for _, child in ipairs(self.children) do + for _, child in ipairs(self._children_) do child._offset_ = Vec3 { start + shift, 0 } shift = shift + child._size_.x end @@ -41,7 +41,7 @@ function element:layout() self._size_ = Vec3 { mainAxisSize, crossAxisSize } end else - for _, child in ipairs(self.children) do + for _, child in ipairs(self._children_) do child._constraints_ = Constraints { maxWidth = self._constraints_.maxWidth } child:layout() if child._size_.x > crossAxisSize then crossAxisSize = child._size_.x end @@ -56,7 +56,7 @@ function element:layout() start = self._constraints_.maxHeight - mainAxisSize end local shift = 0 - for _, child in ipairs(self.children) do + for _, child in ipairs(self._children_) do child._offset_ = Vec3 { 0, start + shift } shift = shift + child._size_.y end diff --git a/lib/simple_ui/level/test.lua b/lib/simple_ui/level/test.lua index 049b639..816fe7c 100644 --- a/lib/simple_ui/level/test.lua +++ b/lib/simple_ui/level/test.lua @@ -18,15 +18,15 @@ Canary.type = "Canary" local reported = false function Canary:build() - self.i = self.i and self.i + 1 or 0 - print(self.i) - -- if not reported then - -- self:traverseUp(function(element) - -- print(element.type) - -- return true - -- end) - -- reported = true - -- end + -- self.i = self.i and self.i + 1 or 0 + -- print(self.i) + if not reported then + self:traverseUp(function(element) + print(element.type) + return true + end) + reported = true + end return Placeholder:new {} end @@ -35,7 +35,7 @@ end --- @return Flex function MyWidget:build() return Flex:new { - key = "my_flex", + key = "test", direction = "vertical", mainAxisSize = "max", children = { @@ -68,6 +68,7 @@ function MyWidget:build() }, Flex:new { key = "inner_flex2", + mainAxisAlignment = "end", children = { SizedBox:new { @@ -81,53 +82,22 @@ function MyWidget:build() height = 100, child = Placeholder:new {} }, + SizedBox:new { + width = 100, + height = 100, + child = Placeholder:new {} + }, }, }, - math.floor(love.timer.getTime()) % 2 == 0 and self.child or nil } } end --- --- --- comment --- --- @return Flex --- function MyWidget:build() --- return Flex:new { --- mainAxisAlignment = "start", --- mainAxisSize = "min", --- children = { --- SizedBox:new { --- width = 100, --- height = 100, --- child = Placeholder:new {} --- }, --- SizedBox:new { --- width = 150, --- height = 200, --- child = Placeholder:new {} --- }, --- SizedBox:new { --- width = 100, --- height = 100, --- child = Canary:new { --- i = 10 --- } --- }, --- }, --- } --- end - return Builder { - elementTree = ScreenArea:new { - child = MyWidget:new { - child = SizedBox:new { - width = 100, - height = 100, - child = Canary:new { - i = 100 - } - } + builder = function() + return ScreenArea:new { + child = MyWidget:new {} } - } + end }