diff --git a/lib/simple_ui/core/builder.lua b/lib/simple_ui/core/builder.lua index 245cf23..48d80d1 100644 --- a/lib/simple_ui/core/builder.lua +++ b/lib/simple_ui/core/builder.lua @@ -3,12 +3,14 @@ local Element = require "lib.simple_ui.core.element" --- Объект, который отвечает за работу с элементами интерфейса одного экрана --- @class UIBuilder --- @field builder fun(): UIElement +--- @field private states {string: table} --- @field private elementTree UIElement local builder = {} builder.__index = builder --- @return UIBuilder local function new(from) + from.states = {} setmetatable(from, builder) return from end @@ -36,7 +38,19 @@ end --- @private function builder:build_step(cur) -- Самоприсваивания должны вырезаться компилятором, я в это верю - cur = cur --[[@as SingleChildElement | MultiChildElement]] + cur = cur --[[@as SingleChildElement | StatefulElement | MultiChildElement]] + + local key = self:makeKey(cur) + if key then + cur = cur --[[@as StatefulElement]] + local storedState = self.states[key] + if not storedState then + self.states[key] = cur.state + else + cur.state = storedState + end + end + local buildRes = cur:build() if not buildRes then return end diff --git a/lib/simple_ui/core/element.lua b/lib/simple_ui/core/element.lua index 98de443..a772d8f 100644 --- a/lib/simple_ui/core/element.lua +++ b/lib/simple_ui/core/element.lua @@ -24,12 +24,6 @@ function element:update(dt) end function element:draw() end ---- @param values {[string]: any} ---- @return UIElement -function element:new(values) - return setmetatable(values, self) -end - --- Рекурсивно обходит дерево элементов вверх, начиная с первого родителя. --- --- К каждому посещенному элементу применяет функцию visitor. @@ -42,4 +36,10 @@ function element:traverseUp(visitor) return self._parent_:traverseUp(visitor) end +--- @param values {[string]: any} +--- @return UIElement +function element:new(values) + return setmetatable(values, self) +end + return element diff --git a/lib/simple_ui/core/stateful_element.lua b/lib/simple_ui/core/stateful_element.lua new file mode 100644 index 0000000..f848b05 --- /dev/null +++ b/lib/simple_ui/core/stateful_element.lua @@ -0,0 +1,17 @@ +local SingleChildElement = require "lib.simple_ui.core.single_child_element" + +--- @generic T : table +--- @class StatefulElement : SingleChildElement +--- @field state T +local element = setmetatable({}, SingleChildElement) +element.__index = element +element.type = "StatefulElement" +element.state = {} + +--- @return StatefulElement +--- @param values {key: any, state: T?, child: UIElement?} +function element:new(values) + return SingleChildElement.new(self, values) +end + +return element diff --git a/lib/simple_ui/level/test.lua b/lib/simple_ui/level/test.lua index 816fe7c..910fdc8 100644 --- a/lib/simple_ui/level/test.lua +++ b/lib/simple_ui/level/test.lua @@ -5,28 +5,23 @@ local Builder = require "lib.simple_ui.core.builder" local Flex = require "lib.simple_ui.elements.flex" local Center = require "lib.simple_ui.elements.center" local SizedBox = require "lib.simple_ui.elements.sized_box" -local SingleChildElement = require "lib.simple_ui.core.single_child_element" +local StatefulElement = require "lib.simple_ui.core.stateful_element" -local MyWidget = setmetatable({}, SingleChildElement) +local MyWidget = setmetatable({}, StatefulElement) MyWidget.__index = MyWidget MyWidget.type = "MyWidget" -local Canary = setmetatable({}, SingleChildElement) +local Canary = setmetatable({}, StatefulElement) Canary.__index = Canary Canary.type = "Canary" -local reported = false +--- @class CanaryState +Canary.state = { i = 0 } + 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.state.i = self.state.i and self.state.i + 1 or 0 + print(self.state.i) return Placeholder:new {} end @@ -56,11 +51,20 @@ function MyWidget:build() child = Placeholder:new {} }, SizedBox:new { - key = "mybox", width = 100, height = 100, child = Canary:new { - i = 0 + key = "canary1", + } + }, + SizedBox:new { + width = 100, + height = 100, + child = Canary:new { + key = "canary2", + state = { + i = 100 + } } }, },