implement MultiChildElement.build
This commit is contained in:
parent
6c8dc6a52b
commit
0e8181baf3
@ -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()
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user