bug fixes and new conf values
This commit is contained in:
parent
91e3441201
commit
81b24eee59
@ -1,6 +1,10 @@
|
||||

|
||||
# Helium
|
||||
|
||||

|
||||
|
||||
*a main menu demo made with helium, in action, find [it here](https://github.com/qeffects/main-menu-example)*
|
||||
|
||||
## Basic overview:
|
||||
Helium is practically more like a UI framework than a fully fledged UI library.
|
||||
The idea is to build custom and build simple.
|
||||
@ -119,4 +123,6 @@ Or continue on to the State and Input guide: [Here](./docs/State-Input-Guide.md)
|
||||
If you are using gamestates, scene guide will be of interest: [Here](./docs/core/Scenes.md)
|
||||
For a more general overview of the whole library: [Module index](./docs/Modules-Index.md)
|
||||
|
||||
Also check out the helium configuration values: [Config](./docs/Configuration.md)
|
||||
|
||||
There's also a main menu example project available here: [Project](https://github.com/qeffects/main-menu-example)
|
||||
|
||||
15
conf.lua
15
conf.lua
@ -1,4 +1,15 @@
|
||||
---@class __HELIUM_CONFIG
|
||||
---@field DEBUG boolean
|
||||
---@field LOAD_HOOKS boolean
|
||||
---@field LOAD_LAYOUT boolean
|
||||
---@field LOAD_SHELL boolean
|
||||
---@field MANUAL_CACHING boolean
|
||||
|
||||
---@type __HELIUM_CONFIG
|
||||
return {
|
||||
AUTO_RUN = true, --Replaces the default love.run
|
||||
DEBUG = true, --Reserved for later
|
||||
DEBUG = true, --Reserved for later
|
||||
LOAD_HOOKS = false, --Loads the hooks module in to helium table
|
||||
LOAD_LAYOUT = false, --Loads the layout module in to helium table
|
||||
LOAD_SHELL = false, --Loads the shell mocule in to helium table
|
||||
MANUAL_CACHING = false, --Whether or not to perform automatic caching
|
||||
}
|
||||
@ -3,7 +3,8 @@
|
||||
Copyright (c) 2021 Elmārs Āboliņš
|
||||
https://github.com/qeffects/helium
|
||||
----------------------------------------------------]]
|
||||
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".core.atlas"))
|
||||
local helium = require(path..'.dummy')
|
||||
local atlas = {}
|
||||
atlas.__index = atlas
|
||||
---@class atlases
|
||||
@ -39,20 +40,22 @@ end
|
||||
function atlases:assign(element)
|
||||
local avg, sum, canvasID = 0, 0, element.context:getCanvasIndex(true) or 1
|
||||
|
||||
for i, e in ipairs(element.renderBench) do
|
||||
sum = sum + e
|
||||
end
|
||||
if not helium.conf.MANUAL_CACHING then
|
||||
for i, e in ipairs(element.renderBench) do
|
||||
sum = sum + e
|
||||
end
|
||||
|
||||
avg = sum/#element.renderBench
|
||||
avg = sum/#element.renderBench
|
||||
|
||||
local areaBelow = self:getFreeArea(canvasID)
|
||||
local area = element.view.h*element.view.w
|
||||
local areaBelow = self:getFreeArea(canvasID)
|
||||
local area = element.view.h*element.view.w
|
||||
|
||||
local areaCoef = (2-(self:getRatio(canvasID)) )-(area/(areaBelow/(4+3*self:getRatio(canvasID))))
|
||||
local speedCoef = avg/selfRenderTime
|
||||
local areaCoef = (2-(self:getRatio(canvasID)) )-(area/(areaBelow/(4+3*self:getRatio(canvasID))))
|
||||
local speedCoef = avg/selfRenderTime
|
||||
|
||||
if not ((areaCoef+speedCoef)>coefficient) then
|
||||
return
|
||||
if not ((areaCoef+speedCoef)>coefficient) then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local elW = element.view.w
|
||||
|
||||
@ -124,7 +124,6 @@ function element:posChange(i, v)
|
||||
if not self.deferRepos then
|
||||
self.deferRepos = true
|
||||
end
|
||||
|
||||
|
||||
if self.callbacks.onPosChange then
|
||||
for i, cb in ipairs(self.callbacks.onPosChange) do
|
||||
@ -258,13 +257,13 @@ local setColor, rectangle, setFont, printf = love.graphics.setColor, love.graphi
|
||||
local calcT
|
||||
|
||||
function element:internalRender()
|
||||
if self.settings.testRenderPasses > 0 and selfRenderTime then
|
||||
if self.settings.testRenderPasses > 0 and selfRenderTime and not helium.conf.MANUAL_CACHING then
|
||||
calcT = love.timer.getTime()
|
||||
end
|
||||
|
||||
self.renderer()
|
||||
|
||||
if self.settings.testRenderPasses > 0 and selfRenderTime then
|
||||
if self.settings.testRenderPasses > 0 and selfRenderTime and not helium.conf.MANUAL_CACHING then
|
||||
self.settings.testRenderPasses = self.settings.testRenderPasses-1
|
||||
local selfTime = love.timer.getTime()-calcT
|
||||
table.insert(self.renderBench, selfTime)
|
||||
@ -334,10 +333,12 @@ end
|
||||
function element:externalUpdate()
|
||||
self.context:set()
|
||||
self.context:zIndex()
|
||||
if not self.settings.failedCanvas
|
||||
if ((not self.settings.failedCanvas
|
||||
and self.settings.testRenderPasses == 0
|
||||
and not self.settings.hasCanvas
|
||||
and scene.activeScene.cached then
|
||||
and scene.activeScene.cached
|
||||
and not helium.conf.MANUAL_CACHING)
|
||||
or self.settings.forcedCanvas)
|
||||
and not self.settings.hasCanvas then
|
||||
|
||||
self:createCanvas()
|
||||
|
||||
|
||||
17
core/init.lua
Normal file
17
core/init.lua
Normal file
@ -0,0 +1,17 @@
|
||||
local path = ...
|
||||
|
||||
---@class __HELIUM_CORE
|
||||
---@field atlas any
|
||||
---@field element any
|
||||
---@field events any
|
||||
---@field input any
|
||||
---@field scene any
|
||||
---@field stack any
|
||||
return {
|
||||
atlas = require(path..'.atlas'),
|
||||
element = require(path..'.element'),
|
||||
events = require(path..'.events'),
|
||||
input = require(path..'.input'),
|
||||
scene = require(path..'.scene'),
|
||||
stack = require(path..'.stack'),
|
||||
}
|
||||
@ -172,11 +172,11 @@ function subscription:emit(...)
|
||||
end
|
||||
|
||||
function subscription:checkInside(x, y)
|
||||
return x>self.stack.absX and x<self.stack.absX+self.w and y>self.stack.absY and y<self.stack.absY+self.h
|
||||
return x>self.x and x<self.x+self.w and y>self.y and y<self.y+self.h
|
||||
end
|
||||
|
||||
function subscription:checkOutside(x, y)
|
||||
return not (x>self.stack.absX and x<self.stack.absX+self.w and y>self.stack.absY and y<self.stack.absY+self.h)
|
||||
return not (x>self.x and x<self.x+self.w and y>self.y and y<self.y+self.h)
|
||||
end
|
||||
|
||||
---@alias InputMouseClickSubscriptionCallback fun(x:number, y:number, mouseButton:string)
|
||||
|
||||
@ -98,8 +98,8 @@ end
|
||||
function scene:drawAtlases(x, y)
|
||||
if self.atlas then
|
||||
local aw = self.atlas.atlases[1].canvas:getWidth()
|
||||
love.graphics.draw(self.atlas.atlases[1].canvas, x, y, 0, 0.5, 0.5)
|
||||
love.graphics.draw(self.atlas.atlases[2].canvas, x+aw/2, y, 0, 0.5, 0.5)
|
||||
love.graphics.draw(self.atlas.atlases[1].canvas, x, y)
|
||||
love.graphics.draw(self.atlas.atlases[2].canvas, x+aw, y)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -8,13 +8,16 @@ local helium = require(path .. ".dummy")
|
||||
local event = require(path..'.core.events')
|
||||
|
||||
---@class context
|
||||
local context = {}
|
||||
---@field element Element
|
||||
local context = {
|
||||
type = 'context'
|
||||
}
|
||||
context.__index = context
|
||||
|
||||
local activeContext
|
||||
local currentTemporalZ = 0
|
||||
|
||||
---@param elem element
|
||||
---@param elem Element
|
||||
function context.new(elem)
|
||||
local ctx = setmetatable({
|
||||
capturedChilds = {},
|
||||
@ -203,9 +206,21 @@ end
|
||||
|
||||
--To be used by the element
|
||||
function context:sizeChanged()
|
||||
if self.parentCtx then
|
||||
self.absX = self.parentCtx.absX + self.view.x
|
||||
self.absY = self.parentCtx.absY + self.view.y
|
||||
else
|
||||
self.absX = self.view.x
|
||||
self.absY = self.view.y
|
||||
end
|
||||
|
||||
self.events:push('resize')
|
||||
end
|
||||
|
||||
local posPropogator = function(elem)
|
||||
elem:posChanged()
|
||||
end
|
||||
|
||||
function context:posChanged()
|
||||
if self.parentCtx then
|
||||
self.absX = self.parentCtx.absX + self.view.x
|
||||
@ -215,6 +230,8 @@ function context:posChanged()
|
||||
self.absY = self.view.y
|
||||
end
|
||||
|
||||
self:doOnEveryChild(posPropogator)
|
||||
|
||||
self.events:push('poschange')
|
||||
end
|
||||
|
||||
@ -235,10 +252,16 @@ function context:offPosChange(callback)
|
||||
self.events:unsub('poschange', callback)
|
||||
end
|
||||
|
||||
function context:onEveryChild(func)
|
||||
func(self.element)
|
||||
function context:doOnEveryChild(func)
|
||||
for i, e in ipairs(self.childrenContexts) do
|
||||
self.childrenContexts:onEveryChild(func)
|
||||
e:onEveryChild(func)
|
||||
end
|
||||
end
|
||||
|
||||
function context:onEveryChild(func)
|
||||
func(self)
|
||||
for i, e in ipairs(self.childrenContexts) do
|
||||
e:onEveryChild(func)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
85
docs/Configuration.md
Normal file
85
docs/Configuration.md
Normal file
@ -0,0 +1,85 @@
|
||||
## Configuration
|
||||
|
||||
Helium offers some configuration values, exposed to you, the user with HELIUM_CONFIG table.
|
||||
|
||||
To start configuring, create a global table before the first helium require like this:
|
||||
|
||||
```lua
|
||||
HELIUM_CONFIG = {
|
||||
LOAD_SHELL = true
|
||||
}
|
||||
|
||||
local helium = require('helium')
|
||||
```
|
||||
|
||||
If the configuration isn't working, you're probably not defining the `HELIUM_CONFIG` table early enough
|
||||
After the first require it's safe to remove `HELIUM_CONFIG` as the values will be copied to an internal table.
|
||||
|
||||
## The current configuration values
|
||||
|
||||
the default value is indicated with () around em:
|
||||
|
||||
options: `other / (default)`
|
||||
|
||||
### LOAD_SHELL
|
||||
|
||||
options: `true / (false)`
|
||||
|
||||
This is an optional config that starts off by default, but it will load all of the ./shell/ modules in to the helium table
|
||||
so you can use it like this later:
|
||||
|
||||
```lua
|
||||
local helium = require('helium')
|
||||
--
|
||||
helium.shell.button()
|
||||
```
|
||||
|
||||
The table structure mirrors the folders exactly, so, instead of
|
||||
|
||||
```lua
|
||||
local checkbox = require('helium.shell.checkbox')
|
||||
```
|
||||
|
||||
You can do
|
||||
|
||||
```lua
|
||||
local helium = require('helium')
|
||||
--
|
||||
helium.shell.checkbox()
|
||||
```
|
||||
|
||||
### LOAD_LAYOUT
|
||||
|
||||
options: `true / (false)`
|
||||
|
||||
This one is extremely similar to LOAD_SHELL, the result is exactly the same, except it loads the ./layout/ folder, and it's also off by default
|
||||
|
||||
so you can do
|
||||
|
||||
```lua
|
||||
local helium = require('helium')
|
||||
--
|
||||
helium.layout.container.new()
|
||||
```
|
||||
|
||||
### LOAD_HOOKS
|
||||
|
||||
options: `true / (false)`
|
||||
|
||||
This one is similar to LOAD_LAYOUT and LOAD_SHELL, the result is the same, except it loads the modules in ./hook/ folder, and it's also off by default
|
||||
|
||||
so you can do
|
||||
|
||||
```lua
|
||||
local helium = require('helium')
|
||||
--
|
||||
helium.hooks.state({blah = false})
|
||||
```
|
||||
|
||||
### MANUAL_CACHING
|
||||
|
||||
options: `true / (false)`
|
||||
|
||||
Manual caching can be enabled if you want manual control over which elements are atlassed, use together with the `setCaching()` hook
|
||||
|
||||
Make sure to enable caching for the scenes you intend to use your element class for.
|
||||
@ -14,7 +14,7 @@ Element is the class for every ui element, in practice it's glue between the cod
|
||||
|
||||
Input allows to create callbacks for helium internal input events
|
||||
|
||||
[Find more here](./core/State-Input-Guide.md)
|
||||
[Find more here](./State-Input-Guide.md)
|
||||
|
||||
[and here](./core/Input-events.md)
|
||||
|
||||
|
||||
@ -245,3 +245,23 @@ function(param, view)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### /hooks/setCaching.lua
|
||||
|
||||
Makes this element get cached, you'll need to set MANUAL_CACHING in config for this to work
|
||||
|
||||
Keep in mind that it won't make a magical performance benefit to an element that is being re-rendered by changes in children components, it's own state, resizing or position changes.
|
||||
|
||||
`setCaching()`
|
||||
|
||||
Usage:
|
||||
|
||||
```lua
|
||||
local setCaching = require('helium.hooks.setCaching')
|
||||
|
||||
function(param, view)
|
||||
setCaching()
|
||||
return function()
|
||||
end
|
||||
end
|
||||
```
|
||||
@ -1,5 +1,5 @@
|
||||
--Allows to expose a function to outside the element simply
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".hooks.onDestroy"))
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".hooks.callback"))
|
||||
local context = require(path.. ".core.stack")
|
||||
|
||||
---Creates a callback on the 'name' field for the current element
|
||||
|
||||
28
hooks/init.lua
Normal file
28
hooks/init.lua
Normal file
@ -0,0 +1,28 @@
|
||||
local path = ...
|
||||
|
||||
---@class __HELIUM_HOOKS
|
||||
---@field callback any
|
||||
---@field context any
|
||||
---@field onDestroy any
|
||||
---@field onLoad any
|
||||
---@field onPosChange any
|
||||
---@field onSizeChange any
|
||||
---@field onUpdate any
|
||||
---@field setMinSize any
|
||||
---@field setPos any
|
||||
---@field setSize any
|
||||
---@field state any
|
||||
return {
|
||||
callback = require(path..'.callback'),
|
||||
context = require(path..'.context'),
|
||||
onDestroy = require(path..'.onDestroy'),
|
||||
onLoad = require(path..'.onLoad'),
|
||||
onPosChange = require(path..'.onPosChange'),
|
||||
onSizeChange = require(path..'.onSizeChange'),
|
||||
onUpdate = require(path..'.onUpdate'),
|
||||
setMinSize = require(path..'.setMinSize'),
|
||||
setCaching = require(path..'.setCaching'),
|
||||
setPos = require(path..'.setPos'),
|
||||
setSize = require(path..'.setSize'),
|
||||
state = require(path..'.state'),
|
||||
}
|
||||
15
hooks/setCaching.lua
Normal file
15
hooks/setCaching.lua
Normal file
@ -0,0 +1,15 @@
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".hooks.setCaching"))
|
||||
---@type context
|
||||
local context = require(path.. ".core.stack")
|
||||
local helium = require(path.. ".dummy")
|
||||
|
||||
return function ()
|
||||
local activeContext = context.getContext()
|
||||
|
||||
if not helium.conf.MANUAL_CACHING then
|
||||
error('use setCaching only with manual caching enabled, check your configs')
|
||||
end
|
||||
activeContext.element:createCanvas()
|
||||
activeContext.element.settings.forcedCanvas = true
|
||||
activeContext.element.settings.pendingUpdate = true
|
||||
end
|
||||
@ -11,7 +11,8 @@ return function (base)
|
||||
local activeContext = context.getContext()
|
||||
return setmetatable({},{
|
||||
__index = function(t, index)
|
||||
return fakeBase[index] or base[index]
|
||||
local f = fakeBase[index] ~= nil and fakeBase[index] or base[index]
|
||||
return f
|
||||
end,
|
||||
__newindex = function(t, index, val)
|
||||
if fakeBase[index] ~= val then
|
||||
|
||||
32
init.lua
32
init.lua
@ -4,10 +4,20 @@
|
||||
https://github.com/qeffects/helium
|
||||
----------------------------------------------------]]
|
||||
local path = ...
|
||||
local helium = require(path..'.dummy')
|
||||
|
||||
---@class __HELIUM
|
||||
---@field private scene any
|
||||
---@field private element any
|
||||
---@field private atlas any
|
||||
---@field private stack any
|
||||
---@field private input any
|
||||
local helium = require(path..'.dummy')
|
||||
helium.__index = helium
|
||||
|
||||
---@type __HELIUM_CONFIG
|
||||
local defaultConf = require(path..".conf")
|
||||
helium.conf = {}
|
||||
|
||||
if HELIUM_CONFIG then
|
||||
for i, e in pairs(defaultConf) do
|
||||
helium.conf[i] = HELIUM_CONFIG[i] or e
|
||||
@ -16,12 +26,28 @@ else
|
||||
helium.conf = defaultConf
|
||||
end
|
||||
|
||||
if helium.conf.LOAD_HOOKS then
|
||||
---@type __HELIUM_HOOKS
|
||||
helium.hooks = require(path..'.hooks')
|
||||
end
|
||||
|
||||
if helium.conf.LOAD_SHELL then
|
||||
---@type __HELIUM_SHELL
|
||||
helium.shell = require(path..'.shell')
|
||||
end
|
||||
|
||||
if helium.conf.LOAD_LAYOUT then
|
||||
---@type __HELIUM_LAYOUT
|
||||
helium.layout = require(path..'.layout')
|
||||
end
|
||||
|
||||
helium.core = require(path..'.core')
|
||||
|
||||
helium.scene = require(path..".core.scene")
|
||||
helium.element = require(path..".core.element")
|
||||
helium.input = require(path..".core.input")
|
||||
helium.stack = require(path..".core.stack")
|
||||
helium.atlas = require(path..".core.atlas")
|
||||
helium.__index = helium
|
||||
|
||||
function helium.setBench(time)
|
||||
helium.benchNum = time
|
||||
@ -39,6 +65,4 @@ setmetatable(helium, {__call = function(s, chunk)
|
||||
end,})
|
||||
end})
|
||||
|
||||
--Typescript
|
||||
helium.helium = helium
|
||||
return helium
|
||||
@ -1,5 +1,5 @@
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".column"))
|
||||
local layout = require(path..'.init')
|
||||
local layout = require(path..'.layout')
|
||||
---@class Column
|
||||
local column = {}
|
||||
column.__index = column
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".container"))
|
||||
local layout = require(path..'.init')
|
||||
local layout = require(path..'.layout')
|
||||
|
||||
---@class Container
|
||||
local container = {}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
local column = require "helium.layout.column"
|
||||
--my copy of the cssssss grids
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".grid"))
|
||||
local layout = require(path..'.init')
|
||||
local layout = require(path..'.layout')
|
||||
|
||||
---@class GridCell
|
||||
---@field name string @Will find the element with the relevant flag
|
||||
@ -350,7 +350,7 @@ function grid:draw(xRoot, yRoot, width, height, children)
|
||||
y = alignHandlerY(self.gridLayout.verticalAlignMode, carriagePos, rowSize, h)
|
||||
end
|
||||
|
||||
e:draw(x, y, w, h)
|
||||
e:draw(x, y + yRoot, w, h)
|
||||
|
||||
carriagePos = carriagePos + self.gridLayout.rowSpacing + rowSize
|
||||
row = row + 1
|
||||
|
||||
171
layout/init.lua
171
layout/init.lua
@ -1,156 +1,15 @@
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".layout.init"))
|
||||
|
||||
---@class layout
|
||||
---@field protected vars table
|
||||
---@field protected type function
|
||||
local layout = {}
|
||||
local layouts = {}
|
||||
layout.__index = layout
|
||||
local element = require(path..'.core.element')
|
||||
local stack = require(path..'.core.stack')
|
||||
|
||||
--Start prep phase
|
||||
function layout.type(binder, callback)
|
||||
local curStack = stack.getContext()
|
||||
curStack:startDeferingChildren()
|
||||
|
||||
local self = {
|
||||
vars = {
|
||||
offLeft = 0,
|
||||
offTop = 0,
|
||||
width = 1,
|
||||
hpad = 3,
|
||||
vpad = 3,
|
||||
height = 1,
|
||||
},
|
||||
stack = curStack,
|
||||
binder = binder,
|
||||
callback = callback,
|
||||
}
|
||||
|
||||
return setmetatable(self, layout)
|
||||
end
|
||||
|
||||
---Aligns the container vertically
|
||||
---@param pos 'left'|'center'|'right'
|
||||
function layout:alignVert(pos)
|
||||
self.vars.alignY = pos
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Aligns the container horizontally
|
||||
---@param pos 'top'|'center'|'bottom'
|
||||
function layout:alignHoriz(pos)
|
||||
self.vars.alignX = pos
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Sets up the width of the box of the layout
|
||||
---@param w number width in pixels or absolute 0-1
|
||||
function layout:width(w)
|
||||
self.vars.width = w
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Sets up the height of the box of the layout
|
||||
---@param h number width in pixels or absolute 0-1
|
||||
function layout:height(h)
|
||||
self.vars.height = h
|
||||
|
||||
return self
|
||||
end
|
||||
---Offset from the left
|
||||
---@param x number offset in pixels or absolute 0-1
|
||||
function layout:left(x)
|
||||
self.vars.offLeft = x
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Offset from the right
|
||||
---@param x number offset in pixels or absolute 0-1
|
||||
function layout:right(x)
|
||||
self.vars.offRight = x
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Offset from the top
|
||||
---@param y number offset in pixels or absolute 0-1
|
||||
function layout:top(y)
|
||||
self.vars.offTop = y
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Offset from the bottom
|
||||
---@param y number offset in pixels or absolute 0-1
|
||||
function layout:bottom(y)
|
||||
self.vars.offBot = y
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Padding for the elements vertically
|
||||
---@param px number offset in pixels
|
||||
function layout:vPadding(px)
|
||||
self.vars.vpad = px
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Padding for the elements horizontally
|
||||
---@param px number offset in pixels
|
||||
function layout:hPadding(px)
|
||||
self.vars.hpad = px
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--Schemes: left + right = width ignored
|
||||
--top + bottom = height ignored
|
||||
--top px + bottom relative works
|
||||
--left relative + bottom px works
|
||||
|
||||
|
||||
function layout:draw()
|
||||
local stack = self.stack
|
||||
local children = stack:stopDeferingChildren()
|
||||
local height, width, x, y, _, marginV, marginH
|
||||
local maxW, maxH = stack:normalizeSize(1,1)
|
||||
|
||||
if self.vars.offTop and self.vars.offBot then
|
||||
marginV = stack:normY(self.vars.offTop) + stack:normY(self.vars.offBot)
|
||||
height = stack:normY(1) - marginV
|
||||
y = self.vars.offTop
|
||||
elseif self.vars.offTop then
|
||||
y = stack:normY(self.vars.offTop)
|
||||
height = math.min(stack:normY(self.vars.height), maxH-y)
|
||||
elseif self.vars.offBot then
|
||||
y = stack:normY(self.vars.offBot)
|
||||
height = math.min(stack:normY(self.vars.height), maxH-y)
|
||||
y = 0
|
||||
end
|
||||
|
||||
if self.vars.offLeft and self.vars.offRight then
|
||||
marginH = stack:normX(self.vars.offLeft) + stack:normX(self.vars.offRight)
|
||||
width = stack:normX(1) - marginH
|
||||
x = self.vars.offLeft
|
||||
elseif self.vars.offLeft then
|
||||
x = stack:normX(self.vars.offLeft)
|
||||
width = math.min(stack:normX(self.vars.width), maxW-x)
|
||||
elseif self.vars.offRight then
|
||||
x = stack:normX(self.vars.offRight)
|
||||
height = math.min(stack:normX(self.vars.width), maxW-x)
|
||||
x = 0
|
||||
end
|
||||
|
||||
self.callback(self.binder, x, y, width, height, children, self.vars.hpad, self.vars.vpad)
|
||||
end
|
||||
|
||||
|
||||
setmetatable(layout, {__call = function(s, binder, callback) return layout.type(binder, callback) end })
|
||||
return layout
|
||||
local path = ...
|
||||
|
||||
---@class __HELIUM_LAYOUT
|
||||
---@field column any
|
||||
---@field container any
|
||||
---@field grid any
|
||||
---@field layout any
|
||||
---@field row any
|
||||
return {
|
||||
column = require(path..'.column'),
|
||||
container = require(path..'.container'),
|
||||
grid = require(path..'.grid'),
|
||||
layout = require(path..'.layout'),
|
||||
row = require(path..'.row'),
|
||||
}
|
||||
154
layout/layout.lua
Normal file
154
layout/layout.lua
Normal file
@ -0,0 +1,154 @@
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".layout.layout"))
|
||||
|
||||
---@class layout
|
||||
---@field protected vars table
|
||||
---@field protected type function
|
||||
local layout = {}
|
||||
local layouts = {}
|
||||
layout.__index = layout
|
||||
local element = require(path..'.core.element')
|
||||
local stack = require(path..'.core.stack')
|
||||
|
||||
--Start prep phase
|
||||
function layout.type(binder, callback)
|
||||
local curStack = stack.getContext()
|
||||
curStack:startDeferingChildren()
|
||||
|
||||
local self = {
|
||||
vars = {
|
||||
width = 1,
|
||||
hpad = 3,
|
||||
vpad = 3,
|
||||
height = 1,
|
||||
},
|
||||
stack = curStack,
|
||||
binder = binder,
|
||||
callback = callback,
|
||||
}
|
||||
|
||||
return setmetatable(self, layout)
|
||||
end
|
||||
|
||||
---Aligns the container vertically
|
||||
---@param pos 'left'|'center'|'right'
|
||||
function layout:alignVert(pos)
|
||||
self.vars.alignY = pos
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Aligns the container horizontally
|
||||
---@param pos 'top'|'center'|'bottom'
|
||||
function layout:alignHoriz(pos)
|
||||
self.vars.alignX = pos
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Sets up the width of the box of the layout
|
||||
---@param w number width in pixels or absolute 0-1
|
||||
function layout:width(w)
|
||||
self.vars.width = w
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Sets up the height of the box of the layout
|
||||
---@param h number width in pixels or absolute 0-1
|
||||
function layout:height(h)
|
||||
self.vars.height = h
|
||||
|
||||
return self
|
||||
end
|
||||
---Offset from the left
|
||||
---@param x number offset in pixels or absolute 0-1
|
||||
function layout:left(x)
|
||||
self.vars.offLeft = x
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Offset from the right
|
||||
---@param x number offset in pixels or absolute 0-1
|
||||
function layout:right(x)
|
||||
self.vars.offRight = x
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Offset from the top
|
||||
---@param y number offset in pixels or absolute 0-1
|
||||
function layout:top(y)
|
||||
self.vars.offTop = y
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Offset from the bottom
|
||||
---@param y number offset in pixels or absolute 0-1
|
||||
function layout:bottom(y)
|
||||
self.vars.offBot = y
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Padding for the elements vertically
|
||||
---@param px number offset in pixels
|
||||
function layout:vPadding(px)
|
||||
self.vars.vpad = px
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Padding for the elements horizontally
|
||||
---@param px number offset in pixels
|
||||
function layout:hPadding(px)
|
||||
self.vars.hpad = px
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--Schemes: left + right = width ignored
|
||||
--top + bottom = height ignored
|
||||
--top px + bottom relative works
|
||||
--left relative + bottom px works
|
||||
|
||||
|
||||
function layout:draw()
|
||||
local stack = self.stack
|
||||
local children = stack:stopDeferingChildren()
|
||||
local height, width, x, y, _, marginV, marginH
|
||||
local maxW, maxH = stack:normalizeSize(1,1)
|
||||
|
||||
if self.vars.offTop and self.vars.offBot then
|
||||
marginV = stack:normY(self.vars.offTop) + stack:normY(self.vars.offBot)
|
||||
height = stack:normY(1) - marginV
|
||||
y = stack:normY(self.vars.offTop)
|
||||
elseif self.vars.offBot then
|
||||
y = stack:normY(self.vars.offBot)
|
||||
height = math.min(stack:normY(self.vars.height), maxH-y)
|
||||
y = maxH - height - y
|
||||
else
|
||||
y = stack:normY(self.vars.offTop or 0)
|
||||
height = math.min(stack:normY(self.vars.height), maxH-y)
|
||||
end
|
||||
|
||||
if self.vars.offLeft and self.vars.offRight then
|
||||
marginH = stack:normX(self.vars.offLeft) + stack:normX(self.vars.offRight)
|
||||
width = stack:normX(1) - marginH
|
||||
x = stack:normX(self.vars.offLeft)
|
||||
elseif self.vars.offRight then
|
||||
x = stack:normX(self.vars.offRight)
|
||||
width = math.min(stack:normX(self.vars.width), maxW-x)
|
||||
x = maxW - width -h
|
||||
else
|
||||
x = stack:normX(self.vars.offLeft or 0)
|
||||
width = math.min(stack:normX(self.vars.width), maxW-x)
|
||||
end
|
||||
|
||||
self.callback(self.binder, x, y, width, height, children, self.vars.hpad, self.vars.vpad)
|
||||
end
|
||||
|
||||
|
||||
setmetatable(layout, {__call = function(s, binder, callback) return layout.type(binder, callback) end })
|
||||
return layout
|
||||
@ -1,5 +1,5 @@
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".row"))
|
||||
local layout = require(path..'.init')
|
||||
local layout = require(path..'.layout')
|
||||
|
||||
---@class Row
|
||||
local row = {}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".shell.button"))
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".shell.checkbox"))
|
||||
local state = require(path.. ".hooks.state")
|
||||
local input = require(path.. ".core.input")
|
||||
|
||||
|
||||
13
shell/init.lua
Normal file
13
shell/init.lua
Normal file
@ -0,0 +1,13 @@
|
||||
local path = ...
|
||||
|
||||
---@class __HELIUM_SHELL
|
||||
---@field button any
|
||||
---@field checkbox any
|
||||
---@field input any
|
||||
---@field slider any
|
||||
return {
|
||||
button = require(path..'.button'),
|
||||
checkbox = require(path..'.checkbox'),
|
||||
input = require(path..'.input'),
|
||||
slider = require(path..'.slider'),
|
||||
}
|
||||
@ -47,14 +47,14 @@ return function(onChange, onFinish, startStr, onEnter, onExit, x, y, w, h)
|
||||
onFinish(textState.text)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end, false)
|
||||
|
||||
textInput = input('textinput', function(text)
|
||||
textState.text = textState.text .. text
|
||||
if onChange then
|
||||
onChange(textState.text)
|
||||
end
|
||||
end)
|
||||
end, false)
|
||||
|
||||
input('mousepressed', function()
|
||||
textState.focused = true
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user