From 393638bb714724948ac0b7ee4a1e3605cffd359a Mon Sep 17 00:00:00 2001 From: PeaAshMeter Date: Mon, 4 May 2026 02:48:30 +0300 Subject: [PATCH] add type hints for EVERYTHING organize ui into folders implement element:traverseUp --- lib/simple_ui/{ => core}/builder.lua | 1 + lib/simple_ui/{ => core}/color.lua | 0 lib/simple_ui/{ => core}/constraints.lua | 2 +- lib/simple_ui/{ => core}/element.lua | 26 ++++++++----- .../{ => core}/multi_child_element.lua | 14 ++++++- lib/simple_ui/{ => core}/rect.lua | 0 .../{ => core}/single_child_element.lua | 13 ++++++- lib/simple_ui/core/types.d.lua | 3 ++ lib/simple_ui/{ => elements}/center.lua | 10 ++++- lib/simple_ui/{ => elements}/flex.lua | 31 +++++++++------ lib/simple_ui/{ => elements}/padding.lua | 10 ++++- lib/simple_ui/{ => elements}/placeholder.lua | 10 ++++- lib/simple_ui/{ => elements}/screen_area.lua | 10 ++++- lib/simple_ui/elements/sized_box.lua | 29 ++++++++++++++ lib/simple_ui/level/test.lua | 39 ++++++++++++------- lib/simple_ui/sized_box.lua | 24 ------------ 16 files changed, 150 insertions(+), 72 deletions(-) rename lib/simple_ui/{ => core}/builder.lua (98%) rename lib/simple_ui/{ => core}/color.lua (100%) rename lib/simple_ui/{ => core}/constraints.lua (80%) rename lib/simple_ui/{ => core}/element.lua (55%) rename lib/simple_ui/{ => core}/multi_child_element.lua (71%) rename lib/simple_ui/{ => core}/rect.lua (100%) rename lib/simple_ui/{ => core}/single_child_element.lua (52%) create mode 100644 lib/simple_ui/core/types.d.lua rename lib/simple_ui/{ => elements}/center.lua (66%) rename lib/simple_ui/{ => elements}/flex.lua (74%) rename lib/simple_ui/{ => elements}/padding.lua (78%) rename lib/simple_ui/{ => elements}/placeholder.lua (73%) rename lib/simple_ui/{ => elements}/screen_area.lua (68%) create mode 100644 lib/simple_ui/elements/sized_box.lua delete mode 100644 lib/simple_ui/sized_box.lua diff --git a/lib/simple_ui/builder.lua b/lib/simple_ui/core/builder.lua similarity index 98% rename from lib/simple_ui/builder.lua rename to lib/simple_ui/core/builder.lua index 748df2e..d3878e4 100644 --- a/lib/simple_ui/builder.lua +++ b/lib/simple_ui/core/builder.lua @@ -42,6 +42,7 @@ function builder:build_step(cur) if not cur then return end if cur.build then cur.child = self:_get(cur:build()) + cur.child.parent = cur self:build_step(cur.child) elseif cur.children then for _, child in ipairs(cur.children) do diff --git a/lib/simple_ui/color.lua b/lib/simple_ui/core/color.lua similarity index 100% rename from lib/simple_ui/color.lua rename to lib/simple_ui/core/color.lua diff --git a/lib/simple_ui/constraints.lua b/lib/simple_ui/core/constraints.lua similarity index 80% rename from lib/simple_ui/constraints.lua rename to lib/simple_ui/core/constraints.lua index ab54dff..3ea1798 100644 --- a/lib/simple_ui/constraints.lua +++ b/lib/simple_ui/core/constraints.lua @@ -12,7 +12,7 @@ local constraints = { constraints.__index = constraints ---- @param from {minWidth?: number, maxWidth?: number, minHeight?: number, maxHeight?: number} +--- @param from {minWidth: number?, maxWidth: number?, minHeight: number?, maxHeight: number?} --- @return Constraints local function new(from) return setmetatable(from, constraints) diff --git a/lib/simple_ui/element.lua b/lib/simple_ui/core/element.lua similarity index 55% rename from lib/simple_ui/element.lua rename to lib/simple_ui/core/element.lua index a4c5a3f..721704d 100644 --- a/lib/simple_ui/element.lua +++ b/lib/simple_ui/core/element.lua @@ -1,5 +1,4 @@ -local Rect = require "lib.simple_ui.rect" -local Constraints = require "lib.simple_ui.constraints" +local Constraints = require "lib.simple_ui.core.constraints" local Vec3 = require "lib.utils.vec3" --- @class UIElement @@ -26,15 +25,22 @@ function element:update(dt) end function element:draw() end ---- @generic T : UIElement ---- @param values T ---- @param self T ---- @return T -function element.new(self, values) - values.bounds = values.bounds or Rect {} - values.transform = values.transform or love.math.newTransform() - if values.child then values.child.parent = values end +--- @param values {[string]: any} +--- @return UIElement +function element:new(values) return setmetatable(values, self) end +--- Рекурсивно обходит дерево элементов вверх, начиная с первого родителя. +--- +--- К каждому посещенному элементу применяет функцию visitor. +--- +--- Обход заканчивается, если visitor возвращает false, или если родители кончились. +--- @param visitor fun(element: UIElement): boolean +function element:traverseUp(visitor) + if not self.parent then return end + if not visitor(self.parent) then return end + return self.parent:traverseUp(visitor) +end + return element diff --git a/lib/simple_ui/multi_child_element.lua b/lib/simple_ui/core/multi_child_element.lua similarity index 71% rename from lib/simple_ui/multi_child_element.lua rename to lib/simple_ui/core/multi_child_element.lua index ef5d66d..f3b1810 100644 --- a/lib/simple_ui/multi_child_element.lua +++ b/lib/simple_ui/core/multi_child_element.lua @@ -1,6 +1,8 @@ +local Element = require "lib.simple_ui.core.element" + --- @class MultiChildElement : UIElement --- @field children UIElement[] -local element = setmetatable({}, require "lib.simple_ui.element") +local element = setmetatable({}, require "lib.simple_ui.core.element") element.__index = element element.children = {} @@ -26,4 +28,14 @@ function element:draw() love.graphics.setColor(1, 1, 1) end +--- @generic T : MultiChildElement +--- @param values {children: UIElement[]?, [string]: any} +--- @return T +function element:new(values) + for _, child in ipairs(values.children or {}) do + child.parent = values + end + return Element.new(self, values) +end + return element diff --git a/lib/simple_ui/rect.lua b/lib/simple_ui/core/rect.lua similarity index 100% rename from lib/simple_ui/rect.lua rename to lib/simple_ui/core/rect.lua diff --git a/lib/simple_ui/single_child_element.lua b/lib/simple_ui/core/single_child_element.lua similarity index 52% rename from lib/simple_ui/single_child_element.lua rename to lib/simple_ui/core/single_child_element.lua index 45602f3..b2a8677 100644 --- a/lib/simple_ui/single_child_element.lua +++ b/lib/simple_ui/core/single_child_element.lua @@ -1,6 +1,8 @@ +local Element = require "lib.simple_ui.core.element" + --- @class SingleChildElement : UIElement --- @field child? UIElement -local element = setmetatable({}, require "lib.simple_ui.element") +local element = setmetatable({}, require "lib.simple_ui.core.element") element.__index = element function element:layout() @@ -17,4 +19,13 @@ function element:draw() if self.child then self.child:draw() end end +--- @generic T : SingleChildElement +--- @param self T +--- @param values {child: UIElement?, [string]: any} +--- @return T +function element:new(values) + if values.child then values.child.parent = values end + return Element.new(self, values) +end + return element diff --git a/lib/simple_ui/core/types.d.lua b/lib/simple_ui/core/types.d.lua new file mode 100644 index 0000000..a6bf1bc --- /dev/null +++ b/lib/simple_ui/core/types.d.lua @@ -0,0 +1,3 @@ +--- @alias Axis "horizontal" | "vertical" +--- @alias MainAxisSize "max" | "min" +--- @alias MainAxisAlignment "start" | "center" | "end" diff --git a/lib/simple_ui/center.lua b/lib/simple_ui/elements/center.lua similarity index 66% rename from lib/simple_ui/center.lua rename to lib/simple_ui/elements/center.lua index 994c831..950cf36 100644 --- a/lib/simple_ui/center.lua +++ b/lib/simple_ui/elements/center.lua @@ -1,5 +1,5 @@ -local Constraints = require "lib.simple_ui.constraints" -local SingleChildElement = require "lib.simple_ui.single_child_element" +local Constraints = require "lib.simple_ui.core.constraints" +local SingleChildElement = require "lib.simple_ui.core.single_child_element" --- @class Center : SingleChildElement local element = setmetatable({}, SingleChildElement) @@ -19,4 +19,10 @@ function element:layout() } end +--- @return Center +--- @param values {child: UIElement?} +function element:new(values) + return SingleChildElement.new(self, values) +end + return element diff --git a/lib/simple_ui/flex.lua b/lib/simple_ui/elements/flex.lua similarity index 74% rename from lib/simple_ui/flex.lua rename to lib/simple_ui/elements/flex.lua index c8941d3..3c63cf0 100644 --- a/lib/simple_ui/flex.lua +++ b/lib/simple_ui/elements/flex.lua @@ -1,17 +1,18 @@ -local Constraints = require "lib.simple_ui.constraints" +local Constraints = require "lib.simple_ui.core.constraints" +local MultiChildElement = require "lib.simple_ui.core.multi_child_element" --- @class Flex : MultiChildElement ---- @field direction "horizontal" | "vertical" ---- @field mainAxisSize "max" | "min" ---- @field mainAxisAlignment "start" | "center" | "end" -local flex = setmetatable({}, require "lib.simple_ui.multi_child_element") -flex.__index = flex -flex.type = "Flex" -flex.direction = "horizontal" -flex.mainAxisSize = "max" -flex.mainAxisAlignment = "start" +--- @field direction Axis +--- @field mainAxisSize MainAxisSize +--- @field mainAxisAlignment MainAxisAlignment +local element = setmetatable({}, require "lib.simple_ui.core.multi_child_element") +element.__index = element +element.type = "Flex" +element.direction = "horizontal" +element.mainAxisSize = "max" +element.mainAxisAlignment = "start" -function flex:layout() +function element:layout() local mainAxisSize = 0 local crossAxisSize = 0 if self.direction == "horizontal" then @@ -68,4 +69,10 @@ function flex:layout() end end -return flex +--- @param values {direction: Axis?, mainAxisSize: MainAxisSize?, mainAxisAlignment: MainAxisAlignment?, children: UIElement[]?} +--- @return Flex +function element:new(values) + return MultiChildElement.new(self, values) +end + +return element diff --git a/lib/simple_ui/padding.lua b/lib/simple_ui/elements/padding.lua similarity index 78% rename from lib/simple_ui/padding.lua rename to lib/simple_ui/elements/padding.lua index 07bf43d..80639bd 100644 --- a/lib/simple_ui/padding.lua +++ b/lib/simple_ui/elements/padding.lua @@ -1,5 +1,5 @@ -local Constraints = require "lib.simple_ui.constraints" -local SingleChildElement = require "lib.simple_ui.single_child_element" +local Constraints = require "lib.simple_ui.core.constraints" +local SingleChildElement = require "lib.simple_ui.core.single_child_element" --- @class Padding : SingleChildElement --- @field left number @@ -32,4 +32,10 @@ function element:layout() self.child.offset = self.offset + Vec3 { self.left, self.top } end +--- @return Padding +--- @param values {left: number?, top: number?, right: number?, bottom: number?, child: UIElement?} +function element:new(values) + return SingleChildElement.new(self, values) +end + return element diff --git a/lib/simple_ui/placeholder.lua b/lib/simple_ui/elements/placeholder.lua similarity index 73% rename from lib/simple_ui/placeholder.lua rename to lib/simple_ui/elements/placeholder.lua index 6578e13..93e53d5 100644 --- a/lib/simple_ui/placeholder.lua +++ b/lib/simple_ui/elements/placeholder.lua @@ -1,5 +1,5 @@ -local Constraints = require "lib.simple_ui.constraints" -local SingleChildElement = require "lib.simple_ui.single_child_element" +local Constraints = require "lib.simple_ui.core.constraints" +local SingleChildElement = require "lib.simple_ui.core.single_child_element" --- @class Placeholder : SingleChildElement local element = setmetatable({}, SingleChildElement) @@ -21,4 +21,10 @@ function element:draw() love.graphics.line(self.offset.x, self.offset.y + self.size.y, self.offset.x + self.size.x, self.offset.y) end +--- @return Placeholder +--- @param values {child: UIElement?} +function element:new(values) + return SingleChildElement.new(self, values) +end + return element diff --git a/lib/simple_ui/screen_area.lua b/lib/simple_ui/elements/screen_area.lua similarity index 68% rename from lib/simple_ui/screen_area.lua rename to lib/simple_ui/elements/screen_area.lua index 816f6ba..6f5885c 100644 --- a/lib/simple_ui/screen_area.lua +++ b/lib/simple_ui/elements/screen_area.lua @@ -1,5 +1,5 @@ -local Constraints = require "lib.simple_ui.constraints" -local SingleChildElement = require "lib.simple_ui.single_child_element" +local Constraints = require "lib.simple_ui.core.constraints" +local SingleChildElement = require "lib.simple_ui.core.single_child_element" --- @class ScreenArea : SingleChildElement local element = setmetatable({}, SingleChildElement) @@ -23,4 +23,10 @@ function element:layout() self.child.offset = Vec3 {} end +--- @return ScreenArea +--- @param values {child: UIElement?} +function element:new(values) + return SingleChildElement.new(self, values) +end + return element diff --git a/lib/simple_ui/elements/sized_box.lua b/lib/simple_ui/elements/sized_box.lua new file mode 100644 index 0000000..7d5f5d1 --- /dev/null +++ b/lib/simple_ui/elements/sized_box.lua @@ -0,0 +1,29 @@ +local SingleChildElement = require "lib.simple_ui.core.single_child_element" + +--- @class SizedBox : SingleChildElement +local element = setmetatable({}, require "lib.simple_ui.core.single_child_element") +local Constraints = require("lib.simple_ui.core.constraints") +element.type = "SizedBox" +element.__index = element +element.width = 0 +element.height = 0 + +function element:layout() + self.size = Vec3 { self.width, self.height } + + if not self.child then return end + self.child.constraints = Constraints { + maxWidth = self.width, + maxHeight = self.height, + } + self.child:layout() + self.child.offset = self.offset:copy() +end + +--- @return SizedBox +--- @param values {width: number?, height: number?, 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 2ea40bd..d78e8d0 100644 --- a/lib/simple_ui/level/test.lua +++ b/lib/simple_ui/level/test.lua @@ -1,16 +1,31 @@ -local ScreenArea = require "lib.simple_ui.screen_area" -local Center = require "lib.simple_ui.center" -local Placeholder = require "lib.simple_ui.placeholder" -local Padding = require "lib.simple_ui.padding" -local Builder = require "lib.simple_ui.builder" -local Flex = require "lib.simple_ui.flex" -local SizedBox = require "lib.simple_ui.sized_box" -local SingleChildElement = require "lib.simple_ui.single_child_element" +local ScreenArea = require "lib.simple_ui.elements.screen_area" +local Placeholder = require "lib.simple_ui.elements.placeholder" +local Padding = require "lib.simple_ui.elements.padding" +local Builder = require "lib.simple_ui.core.builder" +local Flex = require "lib.simple_ui.elements.flex" +local SizedBox = require "lib.simple_ui.elements.sized_box" +local SingleChildElement = require "lib.simple_ui.core.single_child_element" local MyWidget = setmetatable({}, SingleChildElement) MyWidget.__index = MyWidget +local Canary = setmetatable({}, SingleChildElement) +Canary.__index = Canary + +local reported = false +function Canary:build() + if not reported then + self:traverseUp(function(element) + print(element.type) + return true + end) + reported = true + end + + return Placeholder:new {} +end + --- comment --- @return Flex function MyWidget:build() @@ -39,7 +54,7 @@ function MyWidget:build() SizedBox:new { width = 100, height = 100, - child = Placeholder:new {} + child = Canary:new {} }, }, } @@ -66,12 +81,6 @@ function MyWidget:build() } end --- function MyWidget:layout() --- if not self.child then return end --- self.child.constraints = self.constraints --- self.child:layout() --- end - return Builder { elementTree = ScreenArea:new { child = MyWidget:new {} diff --git a/lib/simple_ui/sized_box.lua b/lib/simple_ui/sized_box.lua deleted file mode 100644 index 4bb0a2e..0000000 --- a/lib/simple_ui/sized_box.lua +++ /dev/null @@ -1,24 +0,0 @@ ---- @class SizedBox : SingleChildElement -local element = setmetatable({}, require "lib.simple_ui.single_child_element") -local Constraints = require("lib.simple_ui.constraints") -element.type = "SizedBox" -element.__index = element - -function element:layout() - self.size = Vec3 { self.width, self.height } - - if not self.child then return end - self.child.constraints = Constraints { - maxWidth = self.width, - maxHeight = self.height, - } - self.child:layout() - self.child.offset = self.offset:copy() -end - --- function element:draw() --- print('hello2') --- if self.child then self.child:draw() end --- end - -return element