Convert the main menu screen to lua lol

This commit is contained in:
jacqueline
2023-11-12 19:14:09 +11:00
parent 8471046a95
commit 8a0a167adb
206 changed files with 42303 additions and 183 deletions
+6
View File
@@ -0,0 +1,6 @@
BasedOnStyle: llvm
BreakBeforeBraces: Custom
BraceWrapping:
AfterFunction: true
AlignArrayOfStructures: Left
SeparateDefinitionBlocks: Always
+55
View File
@@ -0,0 +1,55 @@
/build
/.vscode
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
tmp.txt
+9
View File
@@ -0,0 +1,9 @@
[submodule "deps/lvgl"]
path = deps/lvgl
url = https://github.com/lvgl/lvgl.git
[submodule "deps/lv_drivers"]
path = deps/lv_drivers
url = https://github.com/lvgl/lv_drivers.git
[submodule "deps/lua-compat-5.3"]
path = deps/lua-compat-5.3
url = https://github.com/lunarmodules/lua-compat-5.3.git
+5
View File
@@ -0,0 +1,5 @@
# Copyright 2023 jacqueline <me@jacqueline.id.au>
#
# SPDX-License-Identifier: GPL-3.0-only
idf_component_register(SRCS "src/luavgl.c" INCLUDE_DIRS "src" REQUIRES "esp-idf-lua" "lvgl")
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Neo Xu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+155
View File
@@ -0,0 +1,155 @@
# lvgl-lua-binding
lua + lvgl = luavgl
**luavgl is currently under development.**
A flappy bird game is ready for showoff. See simulator instructions below which is tested on ubuntu and mac but not windows.
<p align="center">
<img src="https://i.ibb.co/nbgYvZW/flappybird.gif" />
</p>
## Introduction
`luavgl` is a wrapper around lvgl **core** functions and **widgets** with class inherence in mind, which is lvgl trying to do in `C`. Lua makes widgets inherence happens smoothly.
`luavgl` does not support APIs for low level hardware initialization, lvgl setup etc. Those initialization must be done before executing lua scripts.
`luavgl` mainly targets for embedded device, a simulator has been provided for preview and tested on Ubuntu/macOS.
```lua
local root = lvgl.Object()
root:set { w = lvgl.HOR_RES(), h = lvgl.VER_RES() }
-- flex layout and align
root:set {
flex = {
flex_direction = "row",
flex_wrap = "wrap",
justify_content = "center",
align_items = "center",
align_content = "center",
},
w = 300,
h = 75,
align = lvgl.ALIGN.CENTER
}
-- create obj on root
local obj = root:Object()
-- create image on root and set position/img src/etc. properties.
local img = root:Image {
src = "res/image.png",
x = 0,
y = 0,
bg_color = "#112233" -- #RRGGBB, 0xRRGGBB or "#RGB"
pad_all = 0
}
-- change image properties.
img:set {
src = "/assets/lvgl-logo.png",
align = lvgl.ALIGN.CENTER,
}
-- create animation on object
img:Anim {
run = true,
start_value = 0,
end_value = 3600,
duration = 2000,
repeat_count = 2,
path = "bounce",
exec_cb = function(obj, value)
obj:set {
angle = value
}
end
}
-- create Label on root and set its font
local label = root:Label {
text = string.format("Hello %03d", 123),
text_font = lvgl.Font("montserrat", 24, "normal"),
-- or builtin font:
-- text_font = lvgl.BUILTIN_FONT.MONTSERRAT_22,
align = {
type = lvgl.ALIGN.CENTER,
x_ofs = 0,
y_ofs = 100,
}
}
```
### Embedded device
For embedded device, lvgl environment must setup before using `luavgl`. Once `lvgl` and `lua interpreter` are up and running, add the `luavgl.c` to sources for compiling. And make sure `luaopen_lvgl` is added to global lib. Below is example from `simulator/main.c` shows this exact method.
```c
/* add `lvgl` module to global package table */
luaL_requiref(L, "lvgl", luaopen_luavgl, 1);
lua_pop(L, 1);
```
### LuaJIT support
Supporting `LuaJIT` is done by adding `deps/lua-compat-5.3`.
### Developing
I personally using `vscode` plus extension [`Lua`](https://marketplace.visualstudio.com/items?itemName=sumneko.lua).
File `src/lvgl.lua` is used for linting.
<p align="center">
<img src="https://i.ibb.co/NpRWXZ1/luavgl-linting.png" />
</p>
### Run on RTOS nuttx
Check the ready-to-go examples [luavgl-nuttx-example](https://github.com/XuNeo/luavgl-nuttx-example)
### PC simulator
**Currently compile luavgl to `so` or `dll` is NOT available.**
`luavgl` depends on lvgl and various configurations(`lv_conf.h`), thus cannot run without a working lvgl environment.
The simulator provided in this repo can be used as example if `luavgl` is required on PC.
Make sure clone the submodules, luavgl simulator comes directly from lvgl simulator with lua added.
```bash
git clone --recursive https://github.com/XuNeo/luavgl.git
# or
git sudmodule update --init
```
#### Dependencies
To run simulator on PC, make sure `lua` header is available, you may need to install below packages.
```
sudo apt install libsdl2-dev lua5.3 liblua5.3-dev
```
Both lua5.3 and lua5.4 are supported. Versions below 5.2 has not been verified but should work through `deps/lua-compat-5.3`.
#### Build and run
```bash
cmake -Bbuild -DBUILD_SIMULATOR=ON
cd build
make
make run # run simulator
```
## Custom Widget
`luavgl` support custom widget, and use them in `lua` just like lvgl core widgets.
An example is provided in [`simulator/extension.c`](https://github.com/XuNeo/luavgl/blob/master/simulator/extension.c#L62)
For custom widget, it should be registered to Lua after luavgl lib loaded.
+39
View File
@@ -0,0 +1,39 @@
# MIT License
#
# Copyright (c) 2008-2014 CodePoint Ltd, Shift Technology Ltd, and contributors
# Copyright (c) 2019-2021 The RmlUi Team, and contributors
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Try to find the lua library
# LUAJIT_FOUND - system has lua
# LUAJIT_INCLUDE_DIR - the lua include directory
# LUAJIT_LIBRARY - the lua library
FIND_PATH(LUAJIT_INCLUDE_DIR NAMES luajit.h PATH_SUFFIXES luajit luajit-2.0 luajit-2.1)
SET(_LUAJIT_STATIC_LIBS libluajit-5.1.a libluajit.a liblua51.a)
SET(_LUAJIT_SHARED_LIBS luajit-5.1 luajit lua51)
IF(USE_STATIC_LIBS)
FIND_LIBRARY(LUAJIT_LIBRARY NAMES ${_LUAJIT_STATIC_LIBS} ${_LUAJIT_SHARED_LIBS})
ELSE()
FIND_LIBRARY(LUAJIT_LIBRARY NAMES ${_LUAJIT_SHARED_LIBS} ${_LUAJIT_STATIC_LIBS})
ENDIF()
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJIT DEFAULT_MSG LUAJIT_LIBRARY LUAJIT_INCLUDE_DIR)
MARK_AS_ADVANCED(LUAJIT_LIBRARY LUAJIT_INCLUDE_DIR)
+13
View File
@@ -0,0 +1,13 @@
local analogTime = lvgl.AnalogTime(nil, {
border_width = 0,
x = lvgl.HOR_RES() // 2,
y = lvgl.VER_RES() // 2,
hands = {
hour = SCRIPT_PATH .. "/assets/hand-hour.png",
minute = SCRIPT_PATH .. "/assets/hand-minute.png",
second = SCRIPT_PATH .. "/assets/hand-second.png",
},
period = 33,
})
print("analogTime: ", analogTime)
+61
View File
@@ -0,0 +1,61 @@
local root = lvgl.Object()
root:set { w = lvgl.HOR_RES(), h = lvgl.VER_RES() }
-- create image on root and set position/img src/etc. properties.
root:Object():Image {
src = SCRIPT_PATH .. "/assets/lvgl-logo.png",
x = 0,
y = 0,
bg_color = 0x004400,
pad_all = 0,
align = lvgl.ALIGN.CENTER,
}:Anim {
run = true,
start_value = 0,
end_value = 3600,
duration = 2000,
repeat_count = 2,
path = "bounce",
exec_cb = function(obj, value)
obj:set {
angle = value
}
end,
done_cb = function (anim, obj)
print("anim done.: ", anim, "obj:", obj)
anim:delete()
end
}
-- second anim example with playback
local obj = root:Object {
bg_color = "#F00000",
radius = lvgl.RADIUS_CIRCLE,
align = lvgl.ALIGN.LEFT_MID,
}
obj:clear_flag(lvgl.FLAG.SCROLLABLE)
--- @type AnimPara
local animPara = {
run = true,
start_value = 10,
end_value = 50,
duration = 1000,
playback_delay = 100,
playback_time = 500,
repeat_count = lvgl.ANIM_REPEAT_INFINITE,
path = "ease_in_out",
}
animPara.exec_cb = function(obj, value)
obj:set { size = value }
end
obj:Anim(animPara)
animPara.end_value = 240
animPara.exec_cb = function(obj, value)
obj:set { x = value }
end
obj:Anim(animPara)
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

+74
View File
@@ -0,0 +1,74 @@
-- a dropdown on top left
local dd = lvgl.Dropdown(nil, {
-- note there are two "Orange"
options = "Apple\nBanana\nOrange\nCherry\nGrape\nRaspberry\nMelon\nOrange\nLemon\nNuts",
symbol = "\xEF\x81\x94",
dir = lvgl.DIR.RIGHT,
highlight = false,
text = nil,
align = {
type = lvgl.ALIGN.TOP_LEFT,
x_ofs = 20,
y_ofs = 20,
}
})
local list = dd:get("list")
print("get dropdown list: ", list)
list:set { text_font = lvgl.BUILTIN_FONT.MONTSERRAT_20 }
print("available options:", dd:get("options"))
local cnt = 0
dd:onevent(lvgl.EVENT.VALUE_CHANGED,
---comment
---@param obj Dropdown
---@param code ObjEventCode
function(obj, code)
obj:add_option(string.format("Option:%d", cnt), dd:get("option_cnt"))
cnt = cnt + 1
print(obj:get("selected_str"), "option_cnt" .. obj:get("option_cnt"))
end
)
-- another dropdown on top left
local dd = lvgl.Dropdown(nil, {
options = "Apple\nBanana\nOrange\nCherry\nGrape\nRaspberry\nMelon\nOrange\nLemon\nNuts",
symbol = "\xEF\x81\xB7",
dir = lvgl.DIR.BOTTOM,
text = "SetText",
selected = 5,
text_font = lvgl.BUILTIN_FONT.MONTSERRAT_20,
align = {
type = lvgl.ALIGN.BOTTOM_MID,
x_ofs = 0,
y_ofs = -20,
}
})
dd:get("list"):set { text_font = lvgl.Font("montserrat", 24) }
dd:onevent(lvgl.EVENT.VALUE_CHANGED, function(obj, code)
print(obj:get("selected_str") .. ":" .. obj:get("selected"),
"dir:" .. obj:get("dir"),
"option_index" .. dd:get("option_index", obj:get("selected_str")))
end)
lvgl.Timer {
period = 1000,
cb = function(t)
t:delete()
dd:open()
print("now dd should be opened: " .. (dd:is_open() and "open" or "closed"))
end
}
lvgl.Timer {
period = 2000,
cb = function(t)
t:delete()
dd:close()
print("now dd should be closed: " .. (dd:is_open() and "open" or "closed"))
end
}
+44
View File
@@ -0,0 +1,44 @@
local container = lvgl.Object(nil, {
w = lvgl.HOR_RES(),
h = lvgl.VER_RES(),
bg_color = "#888",
bg_opa = lvgl.OPA(100),
border_width = 0,
radius = 0,
flex = {
flex_direction = "row",
flex_wrap = "wrap"
}
})
print("created container", container)
local function createBtn(parent, name)
local root = parent:Object {
w = lvgl.SIZE_CONTENT,
h = lvgl.SIZE_CONTENT,
bg_color = "#ccc",
bg_opa = lvgl.OPA(100),
border_width = 0,
radius = 10,
pad_all = 20,
}
root:onClicked(function()
container:delete()
require(name)
end)
root:Label {
text = name,
text_color = "#333",
align = lvgl.ALIGN.CENTER,
}
end
createBtn(container, "keyboard")
createBtn(container, "animation")
createBtn(container, "pointer")
createBtn(container, "analogTime")
createBtn(container, "flappyBird/flappyBird")
createBtn(container, "tests")
+14
View File
@@ -0,0 +1,14 @@
-- demo of external widget added to lvgl. See simulator/extension.c
local extension = lvgl.Extension(nil, {
border_width = 1,
w = lvgl.PCT(20),
h = lvgl.PCT(20),
align = lvgl.ALIGN.CENTER,
})
extension:onClicked(function ()
print("clicked")
end)
print("extension: ", extension)
Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -0,0 +1,765 @@
local lvgl = require("lvgl")
local MOVE_SPEED = 480 / 8000 -- 8s for 480 pixel, pixel per ms
local PIXEL_PER_METER = 80
local TOP_Y = 20
local BOTTOM_Y = 480 - 112
local PIPE_COUNT = 5
local PIPE_GAP = 100
local PIPE_SPACE = 120
-- SCRIPT_PATH is set in simulator/main.c, used to get the abs path of first
-- lua script lua get called. In this example, SCRIPT_PATH is set to
-- path of `examples.lua`, flappyBird.lua is called when button is clicked.
local IMAGE_PATH = SCRIPT_PATH
if not IMAGE_PATH then
IMAGE_PATH = "/"
print("Note image root path is set to: ", IMAGE_PATH)
end
IMAGE_PATH = IMAGE_PATH .. "/flappyBird/"
print("IMAGE_PATH:", IMAGE_PATH)
local function randomY()
return math.random(TOP_Y + 30, BOTTOM_Y - 50 - 50)
end
local function screenCreate(parent)
local property = {
w = 480,
h = 480,
bg_opa = 0,
border_width = 0,
pad_all = 0
}
local scr
if parent then
scr = parent:Object{
w = 480,
h = 480,
bg_opa = 0,
border_width = 0,
pad_all = 0
}
else
scr = lvgl.Object(nil, property)
end
scr:clear_flag(lvgl.FLAG.SCROLLABLE)
scr:clear_flag(lvgl.FLAG.CLICKABLE)
return scr
end
local function Image(parent, src)
local img = {}
img.widget = parent:Image{
src = src
}
img.w, img.h = img.widget:get_img_size()
if not img.w or not img.h then
error("failed to load image: " .. src)
end
return img
end
local function ImageScroll(root, src, animSpeed, y)
-- image on right
local right = Image(root, src).widget
right:set{
src = src,
x = 480,
y = y,
pad_all = 0
}
local img = Image(root, src).widget
img:set{
x = 0,
y = y,
src = src,
pad_all = 0
}
img:Anim{
run = true,
start_value = 0,
end_value = -480,
time = 480 / animSpeed,
repeat_count = lvgl.ANIM_REPEAT_INFINITE,
path = "linear",
exec_cb = function(obj, value)
img:set{
x = value
}
right:set{
x = value + 480
}
end
}
img:clear_flag(lvgl.FLAG.CLICKABLE)
return img
end
local function Frames(parent, src, fps)
local frame = Image(parent, src[1])
fps = fps ~= 0 and fps or 25
frame.src = src
frame.len = #src
frame.i = 0
frame.timer = lvgl.Timer {
period = 1000 / fps,
cb = function(t)
frame.widget:set{
src = frame.src[frame.i]
}
frame.i = frame.i + 1
if frame.i == frame.len then
frame.i = 1
end
end
}
frame.start = function(self)
self.timer:resume()
end
frame.pause = function(self)
self.timer:pause()
end
return frame
end
local function Pipe(parent)
local up = Image(parent, IMAGE_PATH .. "pipe_up.png")
local down = Image(parent, IMAGE_PATH .. "pipe_down.png")
local pipe = {
up = up.widget,
down = down.widget,
w = up.w,
h = up.h,
x = 0,
y = 0
}
function pipe:updatePipePos()
self.up:set{
x = self.x,
y = self.y - up.h
}
self.down:set{
x = self.x,
y = self.y + PIPE_GAP
}
end
pipe:updatePipePos()
return pipe
end
local function ObjInfo(x, y, w, h)
return {
x = x,
y = y,
w = w,
h = h
}
end
local function Pipes(parent)
local pipes = {}
-- add initial pipe
for i = 1, PIPE_COUNT do
pipes[i] = Pipe(parent)
if i == 1 then
pipes.w = pipes[i].w -- record pipe size
pipes.h = pipes[i].h
end
end
local function pipesPosinit()
local x = 480;
local y = randomY()
for i = 1, PIPE_COUNT do
local pipe = pipes[i]
pipe.x = x
pipe.y = y
pipe:updatePipePos()
pipes[i] = pipe
x = x + PIPE_SPACE + pipe.w
y = randomY()
end
end
pipesPosinit()
pipes.score = 0
pipes.last = PIPE_COUNT -- first pipe index in pipes.pipes
pipes.totalWidth = (PIPE_COUNT) * (PIPE_SPACE + pipes.w)
pipes.birdInfo = ObjInfo(0, 0, 0, 0)
pipes.gapInfo = ObjInfo(0, 0, 0, 0)
function pipes:setObjInfo(x, y, w, h)
self.birdInfo.x = x
self.birdInfo.y = y
if w then
self.birdInfo.w = w
end
if h then
self.birdInfo.h = h
end
end
local function setGapInfo(x, y, w, h)
pipes.gapInfo.x = x
pipes.gapInfo.y = y
pipes.gapInfo.w = w
pipes.gapInfo.h = h
end
pipes.objPassing = -1
local function isBirdCollision()
local bird = pipes.birdInfo
local gap = pipes.gapInfo
-- far left
if bird.x + bird.w < gap.x then
return false
end
-- far right
if bird.x > gap.x + gap.w then
return false
end
-- in middle
if (bird.y > gap.y) and (bird.y + bird.h < gap.y + gap.h) then
return false
end
return true
end
local function moveVirtualX(dx)
for i = 1, PIPE_COUNT do
local pipe = pipes[i]
local newX = pipe.x + dx
if newX + pipes.w < 0 then
newX = newX + pipes.totalWidth
pipe.y = randomY()
pipes.last = i
end
pipe.x = newX
pipe.updatePipePos(pipe)
end
end
local function checkScore(i)
local pipe = pipes[i]
local bird = pipes.birdInfo
local gap = pipes.gapInfo
local passing = pipes.objPassing
-- far left or right
if bird.x + bird.w < gap.x or bird.x > gap.x + gap.w then
if passing > 0 and i == passing then
pipes.score = pipes.score + 1
passing = -1
pipes.scoreUpdateCB(pipes.score)
end
else
if passing < 0 then
passing = i
end
end
pipes.objPassing = passing
end
--- Detect if obj has collision with pipes
local function collisionDetect()
local first = (pipes.last % PIPE_COUNT) + 1
for idx = 0, PIPE_COUNT - 1 do
local i = (first + idx - 1) % PIPE_COUNT + 1
local pipe = pipes[i]
setGapInfo(pipe.x, pipe.y, pipe.w, PIPE_GAP)
if isBirdCollision() then
local bird = pipes.birdInfo
if pipes.collisionCB then
pipes.collisionCB()
end
end
checkScore(i)
end
end
pipes.preValue = 0
pipes.anim = pipes[1].up:Anim{
run = false,
start_value = 0,
end_value = 480,
time = 480 / MOVE_SPEED, -- MOVE_SPEED
repeat_count = lvgl.ANIM_REPEAT_INFINITE,
path = "linear",
exec_cb = function(obj, value)
local x = pipes.preValue
local d
if value < x then
d = value + 480 - x
else
d = value - x
end
pipes.preValue = value
moveVirtualX(-d)
collisionDetect()
end
}
function pipes:start()
self.anim:start()
end
function pipes:stop()
self.anim:stop()
end
function pipes:reset()
pipesPosinit()
pipes.score = 0
pipes.preValue = 0
pipes.objPassing = -1
end
function pipes:setCollisionCB(collisionCB)
self.collisionCB = collisionCB
end
function pipes:setScoreUpdateCB(cb)
self.scoreUpdateCB = cb
end
return pipes
end
local function Bird(parent, birdMovedCB)
-- create bird Frame(sprite) in 5FPS
local bird = Frames(parent,
{IMAGE_PATH .. "bird1.png", IMAGE_PATH .. "bird2.png", IMAGE_PATH .. "bird3.png"}, 5)
local function birdVarInit()
bird.x = 240 - bird.w / 2
bird.y = 240 - bird.h / 2
bird.widget:set{
x = bird.x,
y = bird.y
}
bird.head = 0
bird.force = 0 -- in unit of m/s^2 rather than N
bird.velocity = 0 -- vertical verlocity
bird.time = 0 -- time stamp when it updates
bird.moving = false
end
birdVarInit()
bird.setY = function(self)
bird.widget:set{
y = bird.y
}
end
bird.setHead = function(self)
bird.widget:set{
angle = self.head
}
end
bird.applyForce = function(self, force)
self.force = force
if bird.moving then
return
end
bird.moving = true
self.y_anim:start()
end
bird.pressed = function(self)
bird:applyForce(-13)
bird.velocity = 0
end
bird.released = function(self)
bird:applyForce(9.8)
bird.velocity = 0
end
local function velocity2HeadAngle(v)
-- -9.8 ~ 9.890 ~ -90
return v * 60
end
-- y moving anim, in time.
bird.y_anim = bird.widget:Anim{
run = false,
start_value = 0,
end_value = 1000,
time = 1000, -- 1000 ms
repeat_count = lvgl.ANIM_REPEAT_INFINITE,
path = "linear",
exec_cb = function(obj, tNow)
-- we use anim to get current time, can calculate position based on force/velocity
if tNow < bird.time then
tNow = tNow + 1000
end
local y = bird.y
local preT = bird.time
local v = bird.velocity
local t = tNow < preT and tNow + 1000 - preT or tNow - preT
t = t * 0.001 -- ms to s
v = bird.force * t + v
if v > 10 then
v = 10
end
if v < -10 then
v = -10
end
y = y + v * t * PIXEL_PER_METER
if y > BOTTOM_Y - 30 then
y = BOTTOM_Y - 30
v = 0
end
if y < TOP_Y then
y = TOP_Y
v = 0
end
bird.y = y
bird.time = tNow
bird.velocity = v
bird.head = velocity2HeadAngle(v)
birdMovedCB(bird.x, bird.y)
-- set y
bird:setY()
bird:setHead()
end
}
function bird:stop()
bird.y_anim:stop()
end
function bird:gameOver()
-- like it's released forever
bird.released()
end
function bird:start()
bird.y_anim:start()
end
function bird:reset()
bird.stop()
birdVarInit()
end
return bird;
end
local function Background(root, bgEventCB)
local bgLayer = screenCreate(root) -- background layer
bgLayer:add_flag(lvgl.FLAG.CLICKABLE) -- we accept event here
local bg = ImageScroll(bgLayer, IMAGE_PATH .. "bg_day.png", MOVE_SPEED * 0.4, 0)
local pipes = Pipes(bgLayer)
local land = ImageScroll(bgLayer, IMAGE_PATH .. "land.png", MOVE_SPEED, BOTTOM_Y)
bgLayer:onevent(lvgl.EVENT.PRESSED, function(obj, code)
bgEventCB(lvgl.EVENT.PRESSED)
end)
bgLayer:onevent(lvgl.EVENT.RELEASED, function(obj, code)
bgEventCB(lvgl.EVENT.RELEASED)
end)
return {
pipes = pipes
}
end
local function SysLayer(root)
local sysLayer = screenCreate(root) -- upper layer
return sysLayer
end
local function createPlayBtn(sysLayer, onEvent)
local playBtn = Image(sysLayer, IMAGE_PATH .. "button_play.png").widget
playBtn:add_flag(lvgl.FLAG.CLICKABLE)
playBtn:set{
align = {
type = lvgl.ALIGN.CENTER,
y_ofs = 80
}
}
playBtn:onevent(lvgl.EVENT.PRESSED, onEvent)
return playBtn
end
local function entry()
local scr = screenCreate()
local bgLayer
local mainLayer
local sysLayer
local bird
local pipes
local bgEventCB -- background layer pressed/released event
local birdMovedCB -- callback when bird position updates
local collisionCB -- callback when collision happends
local flagRunning = false
local gameStart -- API to start game
local gameOver -- API to stop game
local scoreLabel
local scoreBest = 0
local scoreNow = 0
local debouncing = false
-- global event process
local scoreUpdateCB = function(score)
scoreLabel:set{
text = string.format("%03d", score)
}
scoreNow = score
end
print("font:", lvgl.BUILTIN_FONT.MONTSERRAT_26)
gameStart = function()
if flagRunning then
return
end
bird:reset()
pipes:reset()
pipes:start()
bird:start()
flagRunning = true
scoreNow = 0
if scoreLabel then
scoreLabel:set{
text = string.format("%03d", 0)
}
end
end
gameOver = function()
if not flagRunning then
return
end
debouncing = true
flagRunning = false
pipes:stop()
bird:gameOver()
if scoreNow > scoreBest then
scoreBest = scoreNow
end
local gameoverImg = Image(sysLayer, IMAGE_PATH .. "text_game_over.png").widget
gameoverImg:set{
align = {
type = lvgl.ALIGN.TOP_MID,
y_ofs = 100
}
}
gameoverImg:Anim{
run = true,
start_value = 0,
end_value = 3600,
time = 2000,
repeat_count = 2,
path = "bounce",
exec_cb = function(obj, value)
obj:set{
angle = value
}
end
}
local scoreImg = Image(sysLayer, IMAGE_PATH .. "score.png").widget
scoreImg:set{
align = {
type = lvgl.ALIGN.CENTER,
y_ofs = -20,
x_ofs = 0
}
}
scoreImg:Anim{
run = true,
start_value = 480,
end_value = 0,
time = 1000,
repeat_count = 1,
path = "ease_in",
exec_cb = function(obj, value)
obj:set{
align = {
type = lvgl.ALIGN.CENTER,
x_ofs = value,
y_ofs = -20
}
}
end
}
local scoreResultLabel = scoreImg:Label{
text = string.format("%03d", scoreNow),
text_font = lvgl.BUILTIN_FONT.MONTSERRAT_22,
align = {
type = lvgl.ALIGN.TOP_MID,
x_ofs = 0,
y_ofs = 25
}
}
local scoreBestLabel = scoreImg:Label{
text = string.format("%03d", scoreBest),
text_font = lvgl.BUILTIN_FONT.MONTSERRAT_22,
align = {
type = lvgl.ALIGN.BOTTOM_MID,
x_ofs = 0,
y_ofs = -5
}
}
scoreNow = 0
local playBtn;
playBtn = createPlayBtn(sysLayer, function(obj, code)
if debouncing then
return
end
gameStart()
playBtn:delete()
playBtn = nil
gameoverImg:delete()
gameoverImg = nil
scoreImg:delete()
scoreImg = nil
end)
lvgl.Timer {
period = 1000,
cb = function(t)
t:delete()
debouncing = false
end
}
end
bgEventCB = function(event)
if not flagRunning then
return
end
if event == lvgl.EVENT.PRESSED then
bird:pressed()
else
bird:released()
end
end
local birdMovedCB = function(x, y)
pipes:setObjInfo(bird.x, bird.y) -- set intial bird position.
end
local collisionCB = function()
print("bird collision, stop game")
-- call later
lvgl.Timer {
period = 10,
cb = function(t)
t:delete()
gameOver()
end
}
end
-- background layer, including sky, then pipes and land above
bgLayer = Background(scr, bgEventCB) -- background layer
pipes = bgLayer.pipes -- get pipes from bg layer for set bird info etc.
pipes:setCollisionCB(collisionCB)
pipes:setScoreUpdateCB(scoreUpdateCB)
-- main layer, the bird
mainLayer = screenCreate(scr) -- main layer
bird = Bird(mainLayer, birdMovedCB)
pipes:setObjInfo(bird.x, bird.y, bird.w, bird.h)
-- system layer, score etc.
sysLayer = SysLayer(scr)
local title = Image(sysLayer, IMAGE_PATH .. "title.png").widget
title:set{
align = {
type = lvgl.ALIGN.TOP_MID,
y_ofs = 80
}
}
local playBtn;
playBtn = createPlayBtn(sysLayer, function()
print("pressed")
gameStart()
playBtn:delete()
playBtn = nil
title:delete()
title = nil
local medal = Image(sysLayer, IMAGE_PATH .. "medals.png").widget
medal:set{
align = {
type = lvgl.ALIGN.TOP_MID,
y_ofs = 10,
x_ofs = -50
}
}
scoreLabel = sysLayer:Label{
text = " 000",
text_font = lvgl.BUILTIN_FONT.MONTSERRAT_28,
align = {
type = lvgl.ALIGN.TOP_MID,
x_ofs = 10,
y_ofs = 20
}
}
end)
end
entry()
-- bird = Bird(, nil)
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 536 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

+27
View File
@@ -0,0 +1,27 @@
local lvgl = require("lvgl")
local root = lvgl.Object(nil, {
flex = {
flex_direction = "row",
flex_wrap = "wrap",
justify_content = "center",
align_items = "center",
align_content = "center",
},
w = lvgl.HOR_RES(),
h = lvgl.VER_RES(),
align = lvgl.ALIGN.CENTER
})
for i = 1, 10 do
local item = root:Object {
w = 100,
h = lvgl.PCT(100),
}
item:clear_flag(lvgl.FLAG.SCROLLABLE)
local label = item:Label {
text = string.format("label %d", i)
}
label:center()
end
+18
View File
@@ -0,0 +1,18 @@
local label1 = lvgl.Label(nil, {
x = 0, y = 0,
text_font = lvgl.Font("montserrat", 32, "normal"),
text = "Hello Font",
align = lvgl.ALIGN.CENTER
})
print("label1: ", label1)
lvgl.Label(nil, {
-- x= 0, y = 0,
-- text_font = lvgl.Font("MiSansW medium, montserrat", 24),
text_font = lvgl.BUILTIN_FONT.MONTSERRAT_22,
text = "Hello Font2",
}):align_to({
type = lvgl.ALIGN.OUT_BOTTOM_LEFT,
base = label1,
})
+59
View File
@@ -0,0 +1,59 @@
local function fs_example()
-- local f <close>, msg, code = lvgl.open_file(SCRIPT_PATH .. "/tmp.txt") -- for lua 5.4
local f, msg, code = lvgl.fs.open_file(SCRIPT_PATH .. "/tmp.txt", "rw")
if not f then
print("failed: ", msg, code)
return
end
print("f: ", f)
f:write("0123456789", 123, "\n", "the remaining text")
f:seek("set", 0) -- go back
local header, remaining = f:read(10, "*a")
f:close()
if not header then
print("read failed or EOF")
return
end
print("header len:", #header, ": ", header)
print("remaining: ", remaining)
lvgl.Label(nil, {
x = 0,
y = 0,
text_font = lvgl.Font("montserrat", 20, "normal"),
text = header .. remaining,
align = lvgl.ALIGN.TOP_LEFT
})
local list = lvgl.List(nil, {
align = lvgl.ALIGN.TOP_RIGHT,
pad_all = 10,
text_font = lvgl.BUILTIN_FONT.MONTSERRAT_12
})
list:add_text("Directory list:")
-- local dir <close>, msg, code = lvgl.fs.open_dir(SCRIPT_PATH .. "/")
local dir, msg, code = lvgl.fs.open_dir(SCRIPT_PATH .. "/")
if not dir then
print("open dir failed: ", msg, code)
return
end
while true do
local d = dir:read()
if not d then break end
local is_dir = string.byte(d, 1) == string.byte("/", 1)
local str = (is_dir and "dir: " or "file: ") .. d
print(str)
list:add_text(str):set{
border_width = 1,
}
end
dir:close()
end
fs_example()
+61
View File
@@ -0,0 +1,61 @@
local function group_example()
local g = lvgl.group.create()
g:set_default()
-- for demo purpose, set all indev to use this group
local indev = nil
while true do
indev = lvgl.indev.get_next(indev)
if not indev then break end
local t = indev:get_type()
if t == 2 or t == 4 then
indev:set_group(g)
end
end
local style = lvgl.Style({
border_width = 5,
border_color = "#a00",
})
local root = lvgl.Object(nil, {
w = lvgl.PCT(100),
h = lvgl.PCT(100),
align = lvgl.ALIGN.CENTER,
bg_color = "#aaa",
flex = {
flex_direction = "row",
flex_wrap = "wrap"
}
})
root:add_style(style, lvgl.STATE.FOCUSED)
for _ = 1, 5 do
local obj = root:Object({
w = lvgl.PCT(50),
h = lvgl.PCT(50),
bg_color = "#555",
})
obj:add_style(style, lvgl.STATE.FOCUSED)
obj:onClicked(function(obj, code)
print("clicked: ", obj)
end)
obj:onevent(lvgl.EVENT.FOCUSED, function(obj, code)
print("focused: ", obj)
obj:scroll_to_view(true)
end)
obj:onevent(lvgl.EVENT.DEFOCUSED, function(obj, code)
print("defocused: ", obj)
end)
g:add_obj(obj)
end
end
group_example()
+61
View File
@@ -0,0 +1,61 @@
local function indev_example()
local indev = lvgl.indev.get_act()
print("act indev: ", indev)
indev:on_event(lvgl.EVENT.SHORT_CLICKED, function ()
print("indev pressed")
end)
local obj_act = lvgl.indev.get_obj_act()
print("obj_act: ", obj_act)
local root = lvgl.Object(nil, {
w = lvgl.PCT(30),
h = lvgl.PCT(30),
align = lvgl.ALIGN.CENTER,
bg_color = "#aaa",
})
root:Object({
w = 1000,
h = 1000,
align = lvgl.ALIGN.CENTER,
bg_color = "#555",
}):onevent(lvgl.EVENT.ALL, function(obj, code)
local indev = lvgl.indev.get_act()
if not indev then return end
if code == lvgl.EVENT.PRESSED then
local x, y = indev:get_point()
print("pressed: ", x, y)
end
if code == lvgl.EVENT.PRESSING then
local x, y = indev:get_vect()
print("vect: ", x, y)
end
if code == lvgl.EVENT.GESTURE then
local gesture_dir = indev:get_gesture_dir()
print("gesture_dir: ", gesture_dir)
end
if code == lvgl.EVENT.RELEASED then
local scroll_dir = indev:get_scroll_dir()
print("scroll_dir: ", scroll_dir)
local scroll_obj = indev:get_scroll_obj()
print("scroll_obj: ", scroll_obj)
local x, y = indev:get_vect()
local obj_search = obj:indev_search(x, y)
print("indev search obj: ", obj_search)
local obj_search = obj:indev_search({x, y})
print("indev search obj2: ", obj_search)
end
end)
end
indev_example()
+46
View File
@@ -0,0 +1,46 @@
local root = lvgl.Object(nil, {
w = lvgl.HOR_RES(),
h = lvgl.VER_RES(),
pad_all = 0,
bg_color = "#333",
bg_opa = lvgl.OPA(50),
})
root:add_flag(lvgl.FLAG.CLICKABLE)
local ta = root:Textarea {
password_mode = false,
one_line = true,
text_font = lvgl.Font("montserrat", 22),
text_color = "#FFF",
text = "Input text here",
w = lvgl.SIZE_CONTENT,
h = lvgl.SIZE_CONTENT,
bg_opa = 0,
border_width = 2,
pad_all = 2,
align = lvgl.ALIGN.TOP_MID,
}
print("created textarea: ", ta)
local keyboard = root:Keyboard {
textarea = ta,
align = lvgl.ALIGN.BOTTOM_MID,
}
print("created keyboard: ", keyboard)
ta:onevent(lvgl.EVENT.PRESSED, function(obj, code)
keyboard:clear_flag(lvgl.FLAG.HIDDEN)
end)
ta:onevent(lvgl.EVENT.READY, function()
keyboard:add_flag(lvgl.FLAG.HIDDEN)
end)
ta:onevent(lvgl.EVENT.CANCEL, function(obj, code)
keyboard:add_flag(lvgl.FLAG.HIDDEN)
end)
root:onClicked(function (obj, code)
keyboard:add_flag(lvgl.FLAG.HIDDEN)
end)
+46
View File
@@ -0,0 +1,46 @@
local root = lvgl.Object(nil, {
w = 0,
h = 0,
pad_all = 0,
align = lvgl.ALIGN.CENTER,
border_width = 1,
border_color = "#F00",
})
local pointer = root:Pointer {
src = SCRIPT_PATH .. "/assets/second.png",
x = -20,
y = -233,
border_width = 1,
border_color = "#0F0",
range = {
valueStart = 0,
valueRange = 60000,
angleStart = 0,
angleRange = -3600
},
}
-- lvgl requires src set firstly, since lua cannot guarantee table order,
-- we set pivot after image src is set.
pointer:set {
pivot = { x = 20, y = 233 },
}
print("img w,h: ", pointer:get_img_size())
pointer:Anim{
run = true,
start_value = 0,
end_value = 60000,
duration = 60000,
path = "linear",
repeat_count = lvgl.ANIM_REPEAT_INFINITE,
exec_cb = function(obj, value)
obj:set {
value = value
}
end,
}
print("created pointer: ", pointer)
+36
View File
@@ -0,0 +1,36 @@
local function testCrash()
print(nil .. "")
end
local function testCrash2()
testCrash()
end
local function testCrash3()
testCrash2()
end
local function testCrash4()
testCrash3()
end
local function testCrash5()
testCrash4()
end
local function testCrash6()
testCrash5()
end
lvgl.Label(nil, {
text = "crash in 1 second.",
align = lvgl.ALIGN.CENTER
})
lvgl.Timer {
period = 1000,
cb = function(t)
t:delete()
-- crash in callback function is protected.
testCrash6()
end
}
+14
View File
@@ -0,0 +1,14 @@
local roller = lvgl.Roller(nil, {
options = {
options = "January\nFebruary\nMarch\nApril\nMay\nJune\nJuly\nAugust\nSeptember\nOctober\nNovember\nDecember",
mode = lvgl.ROLLER_MODE.INFINITE,
},
visible_cnt = 4,
align = lvgl.ALIGN.CENTER
})
print("create roller:", roller)
roller:onevent(lvgl.EVENT.VALUE_CHANGED, function (obj, code)
print(obj:get_selected_str())
end)
+45
View File
@@ -0,0 +1,45 @@
local container = lvgl.Object(nil, {
w = lvgl.HOR_RES(),
h = lvgl.VER_RES(),
bg_color = "#888",
bg_opa = lvgl.OPA(100),
border_width = 0,
radius = 0,
flex = {
flex_direction = "row",
flex_wrap = "wrap"
}
})
local function createBtn(parent, name)
local root = parent:Object {
w = lvgl.SIZE_CONTENT,
h = lvgl.SIZE_CONTENT,
bg_color = "#ccc",
bg_opa = lvgl.OPA(100),
border_width = 0,
radius = 10,
pad_all = 20,
}
root:onClicked(function()
container:delete()
require(name)
end)
root:Label {
text = name,
text_color = "#333",
align = lvgl.ALIGN.CENTER,
}
end
createBtn(container, "font")
createBtn(container, "uservalue")
createBtn(container, "roller")
createBtn(container, "dropdown")
createBtn(container, "extension")
createBtn(container, "fs")
createBtn(container, "indev")
createBtn(container, "group")
createBtn(container, "protectedcall")
+34
View File
@@ -0,0 +1,34 @@
collectgarbage("collect")
print("initial: ", collectgarbage("count"))
local str_t = {}
for i = 1, 1024 * 1024 do
str_t[#str_t + 1] = 'a'
end
local str = table.concat(str_t)
str_t = nil
collectgarbage("collect")
collectgarbage("collect")
print("after string collect: ", collectgarbage("count"))
for i = 1, 10 do
local label = lvgl.Label(nil)
label:set_text_static(str)
label:delete()
end
str = nil
print("after set text: ", collectgarbage("count"))
collectgarbage("collect")
print("after collect: ", collectgarbage("count"))
print("again: ", collectgarbage("count"))
collectgarbage("collect")
print("again2: ", collectgarbage("count"))
collectgarbage("collect")
print("again3: ", collectgarbage("count"))
local label = lvgl.Label(nil)
label:set({ text = "Test Done" })
label:center()
+13
View File
@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.10)
project(simulator)
add_custom_target(run COMMAND simulator)
file(GLOB_RECURSE WIDGETS ${CMAKE_CURRENT_SOURCE_DIR}/widgets/*.c)
add_executable(simulator main.c mouse_cursor_icon.c ${WIDGETS})
target_include_directories(simulator PRIVATE widgets)
# add_subdirectory(widgets)
target_link_libraries(simulator luavgl lvgl lvgl::demos lvgl::drivers ${SDL2_LIBRARIES} ${LUA_LINK_LIBS})
target_include_directories(simulator PRIVATE ${LUA_INCLUDE_DIRS})
+703
View File
@@ -0,0 +1,703 @@
/**
* @file lv_conf.h
* Configuration file for v8.2.0
*/
/*
* Copy this file as `lv_conf.h`
* 1. simply next to the `lvgl` folder
* 2. or any other places and
* - define `LV_CONF_INCLUDE_SIMPLE`
* - add the path as include path
*/
/* clang-format off */
#if 1 /*Set it to "1" to enable content*/
#ifndef LV_CONF_H
#define LV_CONF_H
#include <stdint.h>
/*====================
COLOR SETTINGS
*====================*/
/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
#define LV_COLOR_DEPTH 32
/*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/
#define LV_COLOR_16_SWAP 0
/*Enable more complex drawing routines to manage screens transparency.
*Can be used if the UI is above another layer, e.g. an OSD menu or video player.
*Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to non LV_OPA_COVER value*/
#define LV_COLOR_SCREEN_TRANSP 0
/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently.
* 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */
#define LV_COLOR_MIX_ROUND_OFS (LV_COLOR_DEPTH == 32 ? 0: 128)
/*Images pixels with this color will not be drawn if they are chroma keyed)*/
#define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/
/*=========================
MEMORY SETTINGS
*=========================*/
/*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/
#define LV_MEM_CUSTOM 0
#if LV_MEM_CUSTOM == 0
/*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
#define LV_MEM_SIZE (10* 1024 * 1024U) /*[bytes]*/
/*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
#define LV_MEM_ADR 0 /*0: unused*/
/*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/
#if LV_MEM_ADR == 0
//#define LV_MEM_POOL_INCLUDE your_alloc_library /* Uncomment if using an external allocator*/
//#define LV_MEM_POOL_ALLOC your_alloc /* Uncomment if using an external allocator*/
#endif
#else /*LV_MEM_CUSTOM*/
#define LV_MEM_CUSTOM_INCLUDE <stdlib.h> /*Header for the dynamic memory function*/
#define LV_MEM_CUSTOM_ALLOC malloc
#define LV_MEM_CUSTOM_FREE free
#define LV_MEM_CUSTOM_REALLOC realloc
#endif /*LV_MEM_CUSTOM*/
/*Number of the intermediate memory buffer used during rendering and other internal processing mechanisms.
*You will see an error log message if there wasn't enough buffers. */
#define LV_MEM_BUF_MAX_NUM 16
/*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/
#define LV_MEMCPY_MEMSET_STD 0
/*====================
HAL SETTINGS
*====================*/
/*Default display refresh period. LVG will redraw changed areas with this period time*/
#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/
/*Input device read period in milliseconds*/
#define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/
/*Use a custom tick source that tells the elapsed time in milliseconds.
*It removes the need to manually update the tick with `lv_tick_inc()`)*/
#define LV_TICK_CUSTOM 1
#if LV_TICK_CUSTOM
#define LV_TICK_CUSTOM_INCLUDE <SDL.h> /*Header for the system time function*/
#define LV_TICK_CUSTOM_SYS_TIME_EXPR SDL_GetTicks() /*Expression evaluating to current system time in ms*/
#endif /*LV_TICK_CUSTOM*/
/*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings.
*(Not so important, you can adjust it to modify default sizes and spaces)*/
#define LV_DPI_DEF 130 /*[px/inch]*/
/*=======================
* FEATURE CONFIGURATION
*=======================*/
/*-------------
* Drawing
*-----------*/
/*Enable complex draw engine.
*Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/
#define LV_DRAW_COMPLEX 1
#if LV_DRAW_COMPLEX != 0
/*Allow buffering some shadow calculation.
*LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius`
*Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/
#define LV_SHADOW_CACHE_SIZE 0
/* Set number of maximally cached circle data.
* The circumference of 1/4 circle are saved for anti-aliasing
* radius * 4 bytes are used per circle (the most often used radiuses are saved)
* 0: to disable caching */
#define LV_CIRCLE_CACHE_SIZE 4
#endif /*LV_DRAW_COMPLEX*/
/*Default image cache size. Image caching keeps the images opened.
*If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added)
*With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images.
*However the opened images might consume additional RAM.
*0: to disable caching*/
#define LV_IMG_CACHE_DEF_SIZE 8
/*Number of stops allowed per gradient. Increase this to allow more stops.
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
#define LV_GRADIENT_MAX_STOPS 2
/*Default gradient buffer size.
*When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again.
*LV_GRAD_CACHE_DEF_SIZE sets the size of this cache in bytes.
*If the cache is too small the map will be allocated only while it's required for the drawing.
*0 mean no caching.*/
#define LV_GRAD_CACHE_DEF_SIZE 512
/*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display)
*LV_DITHER_GRADIENT implies allocating one or two more lines of the object's rendering surface
*The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */
#define LV_DITHER_GRADIENT 1
#if LV_DITHER_GRADIENT
/*Add support for error diffusion dithering.
*Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing.
*The increase in memory consumption is (24 bits * object's width)*/
#define LV_DITHER_ERROR_DIFFUSION 1
#endif
/*Maximum buffer size to allocate for rotation.
*Only used if software rotation is enabled in the display driver.*/
#define LV_DISP_ROT_MAX_BUF (32*1024)
/*-------------
* GPU
*-----------*/
/*Use STM32's DMA2D (aka Chrom Art) GPU*/
#define LV_USE_GPU_STM32_DMA2D 0
#if LV_USE_GPU_STM32_DMA2D
/*Must be defined to include path of CMSIS header of target processor
e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
#define LV_GPU_DMA2D_CMSIS_INCLUDE
#endif
/*Use NXP's PXP GPU iMX RTxxx platforms*/
#define LV_USE_GPU_NXP_PXP 0
#if LV_USE_GPU_NXP_PXP
/*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c)
* and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS
* has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected.
*0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init()
*/
#define LV_USE_GPU_NXP_PXP_AUTO_INIT 0
#endif
/*Use NXP's VG-Lite GPU iMX RTxxx platforms*/
#define LV_USE_GPU_NXP_VG_LITE 0
/*Use SDL renderer API*/
#define LV_USE_GPU_SDL 0
#if LV_USE_GPU_SDL
#define LV_GPU_SDL_INCLUDE_PATH <SDL2/SDL.h>
/*Texture cache size, 8MB by default*/
#define LV_GPU_SDL_LRU_SIZE (1024 * 1024 * 8 )
/*Custom blend mode for mask drawing, disable if you need to link with older SDL2 lib*/
#define LV_GPU_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6))
#endif
/*-------------
* Logging
*-----------*/
/*Enable the log module*/
#define LV_USE_LOG 1
#if LV_USE_LOG
/*How important log should be added:
*LV_LOG_LEVEL_TRACE A lot of logs to give detailed information
*LV_LOG_LEVEL_INFO Log important events
*LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem
*LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail
*LV_LOG_LEVEL_USER Only logs added by the user
*LV_LOG_LEVEL_NONE Do not log anything*/
#define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
/*1: Print the log with 'printf';
*0: User need to register a callback with `lv_log_register_print_cb()`*/
#define LV_LOG_PRINTF 1
/*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/
#define LV_LOG_TRACE_MEM 1
#define LV_LOG_TRACE_TIMER 1
#define LV_LOG_TRACE_INDEV 1
#define LV_LOG_TRACE_DISP_REFR 1
#define LV_LOG_TRACE_EVENT 1
#define LV_LOG_TRACE_OBJ_CREATE 1
#define LV_LOG_TRACE_LAYOUT 1
#define LV_LOG_TRACE_ANIM 1
#endif /*LV_USE_LOG*/
/*-------------
* Asserts
*-----------*/
/*Enable asserts if an operation is failed or an invalid data is found.
*If LV_USE_LOG is enabled an error message will be printed on failure*/
#define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/
#define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/
#define LV_USE_ASSERT_STYLE 1 /*Check if the styles are properly initialized. (Very fast, recommended)*/
#define LV_USE_ASSERT_MEM_INTEGRITY 1 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/
#define LV_USE_ASSERT_OBJ 1 /*Check the object's type and existence (e.g. not deleted). (Slow)*/
/*Add a custom handler when assert happens e.g. to restart the MCU*/
#define LV_ASSERT_HANDLER_INCLUDE <stdint.h>
#define LV_ASSERT_HANDLER while(1); /*Halt by default*/
/*-------------
* Others
*-----------*/
/*1: Show CPU usage and FPS count*/
#define LV_USE_PERF_MONITOR 1
#if LV_USE_PERF_MONITOR
#define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT
#endif
/*1: Show the used memory and the memory fragmentation
* Requires LV_MEM_CUSTOM = 0*/
#define LV_USE_MEM_MONITOR 1
#if LV_USE_MEM_MONITOR
#define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT
#endif
/*1: Draw random colored rectangles over the redrawn areas*/
#define LV_USE_REFR_DEBUG 0
/*Change the built in (v)snprintf functions*/
#define LV_SPRINTF_CUSTOM 0
#if LV_SPRINTF_CUSTOM
#define LV_SPRINTF_INCLUDE <stdio.h>
#define lv_snprintf snprintf
#define lv_vsnprintf vsnprintf
#else /*LV_SPRINTF_CUSTOM*/
#define LV_SPRINTF_USE_FLOAT 0
#endif /*LV_SPRINTF_CUSTOM*/
#define LV_USE_USER_DATA 1
/*Garbage Collector settings
*Used if lvgl is bound to higher level language and the memory is managed by that language*/
#define LV_ENABLE_GC 0
#if LV_ENABLE_GC != 0
#define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/
#endif /*LV_ENABLE_GC*/
/*=====================
* COMPILER SETTINGS
*====================*/
/*For big endian systems set to 1*/
#define LV_BIG_ENDIAN_SYSTEM 0
/*Define a custom attribute to `lv_tick_inc` function*/
#define LV_ATTRIBUTE_TICK_INC
/*Define a custom attribute to `lv_timer_handler` function*/
#define LV_ATTRIBUTE_TIMER_HANDLER
/*Define a custom attribute to `lv_disp_flush_ready` function*/
#define LV_ATTRIBUTE_FLUSH_READY
/*Required alignment size for buffers*/
#define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1
/*Will be added where memories needs to be aligned (with -Os data might not be aligned to boundary by default).
* E.g. __attribute__((aligned(4)))*/
#define LV_ATTRIBUTE_MEM_ALIGN
/*Attribute to mark large constant arrays for example font's bitmaps*/
#define LV_ATTRIBUTE_LARGE_CONST
/*Compiler prefix for a big array declaration in RAM*/
#define LV_ATTRIBUTE_LARGE_RAM_ARRAY
/*Place performance critical functions into a faster memory (e.g RAM)*/
#define LV_ATTRIBUTE_FAST_MEM
/*Prefix variables that are used in GPU accelerated operations, often these need to be placed in RAM sections that are DMA accessible*/
#define LV_ATTRIBUTE_DMA
/*Export integer constant to binding. This macro is used with constants in the form of LV_<CONST> that
*should also appear on LVGL binding API such as Micropython.*/
#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/
/*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/
#define LV_USE_LARGE_COORD 0
/*==================
* FONT USAGE
*===================*/
/*Montserrat fonts with ASCII range and some symbols using bpp = 4
*https://fonts.google.com/specimen/Montserrat*/
#define LV_FONT_MONTSERRAT_8 1
#define LV_FONT_MONTSERRAT_10 1
#define LV_FONT_MONTSERRAT_12 1
#define LV_FONT_MONTSERRAT_14 1
#define LV_FONT_MONTSERRAT_16 1
#define LV_FONT_MONTSERRAT_18 1
#define LV_FONT_MONTSERRAT_20 1
#define LV_FONT_MONTSERRAT_22 1
#define LV_FONT_MONTSERRAT_24 1
#define LV_FONT_MONTSERRAT_26 1
#define LV_FONT_MONTSERRAT_28 1
#define LV_FONT_MONTSERRAT_30 1
#define LV_FONT_MONTSERRAT_32 1
#define LV_FONT_MONTSERRAT_34 1
#define LV_FONT_MONTSERRAT_36 1
#define LV_FONT_MONTSERRAT_38 1
#define LV_FONT_MONTSERRAT_40 1
#define LV_FONT_MONTSERRAT_42 1
#define LV_FONT_MONTSERRAT_44 1
#define LV_FONT_MONTSERRAT_46 1
#define LV_FONT_MONTSERRAT_48 1
/*Demonstrate special features*/
#define LV_FONT_MONTSERRAT_12_SUBPX 1
#define LV_FONT_MONTSERRAT_28_COMPRESSED 1 /*bpp = 3*/
#define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 1 /*Hebrew, Arabic, Persian letters and all their forms*/
#define LV_FONT_SIMSUN_16_CJK 1 /*1000 most common CJK radicals*/
/*Pixel perfect monospace fonts*/
#define LV_FONT_UNSCII_8 1
#define LV_FONT_UNSCII_16 1
/*Optionally declare custom fonts here.
*You can use these fonts as default font too and they will be available globally.
*E.g. #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) LV_FONT_DECLARE(my_font_2)*/
#define LV_FONT_CUSTOM_DECLARE
/*Always set a default font*/
#define LV_FONT_DEFAULT &lv_font_montserrat_14
/*Enable handling large font and/or fonts with a lot of characters.
*The limit depends on the font size, font face and bpp.
*Compiler error will be triggered if a font needs it.*/
#define LV_FONT_FMT_TXT_LARGE 1
/*Enables/disables support for compressed fonts.*/
#define LV_USE_FONT_COMPRESSED 1
/*Enable subpixel rendering*/
#define LV_USE_FONT_SUBPX 1
#if LV_USE_FONT_SUBPX
/*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/
#define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/
#endif
/*=================
* TEXT SETTINGS
*=================*/
/**
* Select a character encoding for strings.
* Your IDE or editor should have the same character encoding
* - LV_TXT_ENC_UTF8
* - LV_TXT_ENC_ASCII
*/
#define LV_TXT_ENC LV_TXT_ENC_UTF8
/*Can break (wrap) texts on these chars*/
#define LV_TXT_BREAK_CHARS " ,.;:-_"
/*If a word is at least this long, will break wherever "prettiest"
*To disable, set to a value <= 0*/
#define LV_TXT_LINE_BREAK_LONG_LEN 0
/*Minimum number of characters in a long word to put on a line before a break.
*Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
/*Minimum number of characters in a long word to put on a line after a break.
*Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
/*The control character to use for signalling text recoloring.*/
#define LV_TXT_COLOR_CMD "#"
/*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts.
*The direction will be processed according to the Unicode Bidirectional Algorithm:
*https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/
#define LV_USE_BIDI 1
#if LV_USE_BIDI
/*Set the default direction. Supported values:
*`LV_BASE_DIR_LTR` Left-to-Right
*`LV_BASE_DIR_RTL` Right-to-Left
*`LV_BASE_DIR_AUTO` detect texts base direction*/
#define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO
#endif
/*Enable Arabic/Persian processing
*In these languages characters should be replaced with an other form based on their position in the text*/
#define LV_USE_ARABIC_PERSIAN_CHARS 0
/*==================
* WIDGET USAGE
*================*/
/*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/
#define LV_USE_ARC 1
#define LV_USE_ANIMIMG 1
#define LV_USE_BAR 1
#define LV_USE_BTN 1
#define LV_USE_BTNMATRIX 1
#define LV_USE_CANVAS 1
#define LV_USE_CHECKBOX 1
#define LV_USE_DROPDOWN 1 /*Requires: lv_label*/
#define LV_USE_IMG 1 /*Requires: lv_label*/
#define LV_USE_LABEL 1
#if LV_USE_LABEL
#define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/
#define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/
#endif
#define LV_USE_LINE 1
#define LV_USE_ROLLER 1 /*Requires: lv_label*/
#if LV_USE_ROLLER
#define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/
#endif
#define LV_USE_SLIDER 1 /*Requires: lv_bar*/
#define LV_USE_SWITCH 1
#define LV_USE_TEXTAREA 1 /*Requires: lv_label*/
#if LV_USE_TEXTAREA != 0
#define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/
#endif
#define LV_USE_TABLE 1
#define LV_USE_POINTER 1
#define LV_USE_ANALOG_TIME 1
/*==================
* EXTRA COMPONENTS
*==================*/
/*-----------
* Widgets
*----------*/
#define LV_USE_CALENDAR 1
#if LV_USE_CALENDAR
#define LV_CALENDAR_WEEK_STARTS_MONDAY 0
#if LV_CALENDAR_WEEK_STARTS_MONDAY
#define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}
#else
#define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"}
#endif
#define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
#define LV_USE_CALENDAR_HEADER_ARROW 1
#define LV_USE_CALENDAR_HEADER_DROPDOWN 1
#endif /*LV_USE_CALENDAR*/
#define LV_USE_CHART 1
#define LV_USE_COLORWHEEL 1
#define LV_USE_IMGBTN 1
#define LV_USE_KEYBOARD 1
#define LV_USE_LED 1
#define LV_USE_LIST 1
#define LV_USE_MENU 1
#define LV_USE_METER 1
#define LV_USE_MSGBOX 1
#define LV_USE_SPINBOX 1
#define LV_USE_SPINNER 1
#define LV_USE_TABVIEW 1
#define LV_USE_TILEVIEW 1
#define LV_USE_WIN 1
#define LV_USE_SPAN 1
#if LV_USE_SPAN
/*A line text can contain maximum num of span descriptor */
#define LV_SPAN_SNIPPET_STACK_SIZE 64
#endif
/*-----------
* Themes
*----------*/
/*A simple, impressive and very complete theme*/
#define LV_USE_THEME_DEFAULT 1
#if LV_USE_THEME_DEFAULT
/*0: Light mode; 1: Dark mode*/
#define LV_THEME_DEFAULT_DARK 0
/*1: Enable grow on press*/
#define LV_THEME_DEFAULT_GROW 1
/*Default transition time in [ms]*/
#define LV_THEME_DEFAULT_TRANSITION_TIME 80
#endif /*LV_USE_THEME_DEFAULT*/
/*A very simple theme that is a good starting point for a custom theme*/
#define LV_USE_THEME_BASIC 1
/*A theme designed for monochrome displays*/
#define LV_USE_THEME_MONO 1
/*-----------
* Layouts
*----------*/
/*A layout similar to Flexbox in CSS.*/
#define LV_USE_FLEX 1
/*A layout similar to Grid in CSS.*/
#define LV_USE_GRID 1
/*---------------------
* 3rd party libraries
*--------------------*/
/*File system interfaces for common APIs */
/*API for fopen, fread, etc*/
#define LV_USE_FS_STDIO 0
#if LV_USE_FS_STDIO
#define LV_FS_STDIO_LETTER 'A' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
#define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
#endif
/*API for open, read, etc*/
#define LV_USE_FS_POSIX 1
#if LV_USE_FS_POSIX
#define LV_FS_POSIX_LETTER '/' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#define LV_FS_POSIX_PATH "/" /*Set the working directory. File/directory paths will be appended to it.*/
#define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
#endif
/*API for CreateFile, ReadFile, etc*/
#define LV_USE_FS_WIN32 0
#if LV_USE_FS_WIN32
#define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
#define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
#endif
/*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/
#define LV_USE_FS_FATFS 0
#if LV_USE_FS_FATFS
#define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
#endif
/*PNG decoder library*/
#define LV_USE_PNG 1
/*BMP decoder library*/
#define LV_USE_BMP 1
/* JPG + split JPG decoder library.
* Split JPG is a custom format optimized for embedded systems. */
#define LV_USE_SJPG 1
/*GIF decoder library*/
#define LV_USE_GIF 1
/*QR code library*/
#define LV_USE_QRCODE 1
/*FreeType library*/
#define LV_USE_FREETYPE 0
#if LV_USE_FREETYPE
/*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/
#define LV_FREETYPE_CACHE_SIZE (16 * 1024)
#if LV_FREETYPE_CACHE_SIZE >= 0
/* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */
/* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */
/* if font size >= 256, must be configured as image cache */
#define LV_FREETYPE_SBIT_CACHE 0
/* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */
/* (0:use system defaults) */
#define LV_FREETYPE_CACHE_FT_FACES 0
#define LV_FREETYPE_CACHE_FT_SIZES 0
#endif
#endif
/*Rlottie library*/
#define LV_USE_RLOTTIE 0
/*FFmpeg library for image decoding and playing videos
*Supports all major image formats so do not enable other image decoder with it*/
#define LV_USE_FFMPEG 0
#if LV_USE_FFMPEG
/*Dump input information to stderr*/
#define LV_FFMPEG_AV_DUMP_FORMAT 0
#endif
/*-----------
* Others
*----------*/
/*1: Enable API to take snapshot for object*/
#define LV_USE_SNAPSHOT 1
/*1: Enable Monkey test*/
#define LV_USE_MONKEY 1
/*1: Enable grid navigation*/
#define LV_USE_GRIDNAV 1
/*==================
* EXAMPLES
*==================*/
/*Enable the examples to be built with the library*/
#define LV_BUILD_EXAMPLES 1
/*===================
* DEMO USAGE
====================*/
/*Show some widget. It might be required to increase `LV_MEM_SIZE` */
#define LV_USE_DEMO_WIDGETS 1
#if LV_USE_DEMO_WIDGETS
#define LV_DEMO_WIDGETS_SLIDESHOW 0
#endif
/*Demonstrate the usage of encoder and keyboard*/
#define LV_USE_DEMO_KEYPAD_AND_ENCODER 1
/*Benchmark your system*/
#define LV_USE_DEMO_BENCHMARK 1
/*Stress test for LVGL*/
#define LV_USE_DEMO_STRESS 1
/*Music player demo*/
#define LV_USE_DEMO_MUSIC 1
#if LV_USE_DEMO_MUSIC
# define LV_DEMO_MUSIC_SQUARE 0
# define LV_DEMO_MUSIC_LANDSCAPE 0
# define LV_DEMO_MUSIC_ROUND 0
# define LV_DEMO_MUSIC_LARGE 0
# define LV_DEMO_MUSIC_AUTO_PLAY 0
#endif
/*--END OF LV_CONF_H--*/
#endif /*LV_CONF_H*/
#endif /*End of "Content enable"*/
+494
View File
@@ -0,0 +1,494 @@
/**
* @file lv_drv_conf.h
* Configuration file for v8.3.0-dev
*/
/*
* COPY THIS FILE AS lv_drv_conf.h
*/
/* clang-format off */
#if 1 /*Set it to "1" to enable the content*/
#ifndef LV_DRV_CONF_H
#define LV_DRV_CONF_H
#include "lv_conf.h"
/*********************
* DELAY INTERFACE
*********************/
#define LV_DRV_DELAY_INCLUDE <stdint.h> /*Dummy include by default*/
#define LV_DRV_DELAY_US(us) /*delay_us(us)*/ /*Delay the given number of microseconds*/
#define LV_DRV_DELAY_MS(ms) /*delay_ms(ms)*/ /*Delay the given number of milliseconds*/
/*********************
* DISPLAY INTERFACE
*********************/
/*------------
* Common
*------------*/
#define LV_DRV_DISP_INCLUDE <stdint.h> /*Dummy include by default*/
#define LV_DRV_DISP_CMD_DATA(val) /*pin_x_set(val)*/ /*Set the command/data pin to 'val'*/
#define LV_DRV_DISP_RST(val) /*pin_x_set(val)*/ /*Set the reset pin to 'val'*/
/*---------
* SPI
*---------*/
#define LV_DRV_DISP_SPI_CS(val) /*spi_cs_set(val)*/ /*Set the SPI's Chip select to 'val'*/
#define LV_DRV_DISP_SPI_WR_BYTE(data) /*spi_wr(data)*/ /*Write a byte the SPI bus*/
#define LV_DRV_DISP_SPI_WR_ARRAY(adr, n) /*spi_wr_mem(adr, n)*/ /*Write 'n' bytes to SPI bus from 'adr'*/
/*------------------
* Parallel port
*-----------------*/
#define LV_DRV_DISP_PAR_CS(val) /*par_cs_set(val)*/ /*Set the Parallel port's Chip select to 'val'*/
#define LV_DRV_DISP_PAR_SLOW /*par_slow()*/ /*Set low speed on the parallel port*/
#define LV_DRV_DISP_PAR_FAST /*par_fast()*/ /*Set high speed on the parallel port*/
#define LV_DRV_DISP_PAR_WR_WORD(data) /*par_wr(data)*/ /*Write a word to the parallel port*/
#define LV_DRV_DISP_PAR_WR_ARRAY(adr, n) /*par_wr_mem(adr,n)*/ /*Write 'n' bytes to Parallel ports from 'adr'*/
/***************************
* INPUT DEVICE INTERFACE
***************************/
/*----------
* Common
*----------*/
#define LV_DRV_INDEV_INCLUDE <stdint.h> /*Dummy include by default*/
#define LV_DRV_INDEV_RST(val) /*pin_x_set(val)*/ /*Set the reset pin to 'val'*/
#define LV_DRV_INDEV_IRQ_READ 0 /*pn_x_read()*/ /*Read the IRQ pin*/
/*---------
* SPI
*---------*/
#define LV_DRV_INDEV_SPI_CS(val) /*spi_cs_set(val)*/ /*Set the SPI's Chip select to 'val'*/
#define LV_DRV_INDEV_SPI_XCHG_BYTE(data) 0 /*spi_xchg(val)*/ /*Write 'val' to SPI and give the read value*/
/*---------
* I2C
*---------*/
#define LV_DRV_INDEV_I2C_START /*i2c_start()*/ /*Make an I2C start*/
#define LV_DRV_INDEV_I2C_STOP /*i2c_stop()*/ /*Make an I2C stop*/
#define LV_DRV_INDEV_I2C_RESTART /*i2c_restart()*/ /*Make an I2C restart*/
#define LV_DRV_INDEV_I2C_WR(data) /*i2c_wr(data)*/ /*Write a byte to the I1C bus*/
#define LV_DRV_INDEV_I2C_READ(last_read) 0 /*i2c_rd()*/ /*Read a byte from the I2C bud*/
/*********************
* DISPLAY DRIVERS
*********************/
/*-------------------
* SDL
*-------------------*/
/* SDL based drivers for display, mouse, mousewheel and keyboard*/
#ifndef USE_SDL
# define USE_SDL 1
#endif
/* Hardware accelerated SDL driver */
#ifndef USE_SDL_GPU
# define USE_SDL_GPU 0
#endif
#if USE_SDL || USE_SDL_GPU
# define SDL_HOR_RES 480
# define SDL_VER_RES 480
/* Scale window by this factor (useful when simulating small screens) */
# define SDL_ZOOM 1
/* Used to test true double buffering with only address changing.
* Use 2 draw buffers, bith with SDL_HOR_RES x SDL_VER_RES size*/
# define SDL_DOUBLE_BUFFERED 0
/*Eclipse: <SDL2/SDL.h> Visual Studio: <SDL.h>*/
# define SDL_INCLUDE_PATH <SDL2/SDL.h>
/*Open two windows to test multi display support*/
# define SDL_DUAL_DISPLAY 0
#endif
/*-------------------
* Monitor of PC
*-------------------*/
/*DEPRECATED: Use the SDL driver instead. */
#ifndef USE_MONITOR
# define USE_MONITOR 0
#endif
#if USE_MONITOR
# define MONITOR_HOR_RES 480
# define MONITOR_VER_RES 320
/* Scale window by this factor (useful when simulating small screens) */
# define MONITOR_ZOOM 1
/* Used to test true double buffering with only address changing.
* Use 2 draw buffers, bith with MONITOR_HOR_RES x MONITOR_VER_RES size*/
# define MONITOR_DOUBLE_BUFFERED 0
/*Eclipse: <SDL2/SDL.h> Visual Studio: <SDL.h>*/
# define MONITOR_SDL_INCLUDE_PATH <SDL2/SDL.h>
/*Open two windows to test multi display support*/
# define MONITOR_DUAL 0
#endif
/*-----------------------------------
* Native Windows (including mouse)
*----------------------------------*/
#ifndef USE_WINDOWS
# define USE_WINDOWS 0
#endif
#if USE_WINDOWS
# define WINDOW_HOR_RES 480
# define WINDOW_VER_RES 320
#endif
/*----------------------------
* Native Windows (win32drv)
*---------------------------*/
#ifndef USE_WIN32DRV
# define USE_WIN32DRV 0
#endif
#if USE_WIN32DRV
/* Scale window by this factor (useful when simulating small screens) */
# define WIN32DRV_MONITOR_ZOOM 1
#endif
/*----------------------------------------
* GTK drivers (monitor, mouse, keyboard
*---------------------------------------*/
#ifndef USE_GTK
# define USE_GTK 0
#endif
/*----------------------------------------
* Wayland drivers (monitor, mouse, keyboard, touchscreen)
*---------------------------------------*/
#ifndef USE_WAYLAND
# define USE_WAYLAND 0
#endif
#if USE_WAYLAND
/* Support for client-side decorations */
# ifndef LV_WAYLAND_CLIENT_SIDE_DECORATIONS
# define LV_WAYLAND_CLIENT_SIDE_DECORATIONS 1
# endif
/* Support for (deprecated) wl-shell protocol */
# ifndef LV_WAYLAND_WL_SHELL
# define LV_WAYLAND_WL_SHELL 1
# endif
/* Support for xdg-shell protocol */
# ifndef LV_WAYLAND_XDG_SHELL
# define LV_WAYLAND_XDG_SHELL 0
# endif
#endif
/*----------------
* SSD1963
*--------------*/
#ifndef USE_SSD1963
# define USE_SSD1963 0
#endif
#if USE_SSD1963
# define SSD1963_HOR_RES LV_HOR_RES
# define SSD1963_VER_RES LV_VER_RES
# define SSD1963_HT 531
# define SSD1963_HPS 43
# define SSD1963_LPS 8
# define SSD1963_HPW 10
# define SSD1963_VT 288
# define SSD1963_VPS 12
# define SSD1963_FPS 4
# define SSD1963_VPW 10
# define SSD1963_HS_NEG 0 /*Negative hsync*/
# define SSD1963_VS_NEG 0 /*Negative vsync*/
# define SSD1963_ORI 0 /*0, 90, 180, 270*/
# define SSD1963_COLOR_DEPTH 16
#endif
/*----------------
* R61581
*--------------*/
#ifndef USE_R61581
# define USE_R61581 0
#endif
#if USE_R61581
# define R61581_HOR_RES LV_HOR_RES
# define R61581_VER_RES LV_VER_RES
# define R61581_HSPL 0 /*HSYNC signal polarity*/
# define R61581_HSL 10 /*HSYNC length (Not Implemented)*/
# define R61581_HFP 10 /*Horitontal Front poarch (Not Implemented)*/
# define R61581_HBP 10 /*Horitontal Back poarch (Not Implemented */
# define R61581_VSPL 0 /*VSYNC signal polarity*/
# define R61581_VSL 10 /*VSYNC length (Not Implemented)*/
# define R61581_VFP 8 /*Vertical Front poarch*/
# define R61581_VBP 8 /*Vertical Back poarch */
# define R61581_DPL 0 /*DCLK signal polarity*/
# define R61581_EPL 1 /*ENABLE signal polarity*/
# define R61581_ORI 0 /*0, 180*/
# define R61581_LV_COLOR_DEPTH 16 /*Fix 16 bit*/
#endif
/*------------------------------
* ST7565 (Monochrome, low res.)
*-----------------------------*/
#ifndef USE_ST7565
# define USE_ST7565 0
#endif
#if USE_ST7565
/*No settings*/
#endif /*USE_ST7565*/
/*------------------------------
* GC9A01 (color, low res.)
*-----------------------------*/
#ifndef USE_GC9A01
# define USE_GC9A01 0
#endif
#if USE_GC9A01
/*No settings*/
#endif /*USE_GC9A01*/
/*------------------------------------------
* UC1610 (4 gray 160*[104|128])
* (EA DOGXL160 160x104 tested)
*-----------------------------------------*/
#ifndef USE_UC1610
# define USE_UC1610 0
#endif
#if USE_UC1610
# define UC1610_HOR_RES LV_HOR_RES
# define UC1610_VER_RES LV_VER_RES
# define UC1610_INIT_CONTRAST 33 /* init contrast, values in [%] */
# define UC1610_INIT_HARD_RST 0 /* 1 : hardware reset at init, 0 : software reset */
# define UC1610_TOP_VIEW 0 /* 0 : Bottom View, 1 : Top View */
#endif /*USE_UC1610*/
/*-------------------------------------------------
* SHARP memory in pixel monochrome display series
* LS012B7DD01 (184x38 pixels.)
* LS013B7DH03 (128x128 pixels.)
* LS013B7DH05 (144x168 pixels.)
* LS027B7DH01 (400x240 pixels.) (tested)
* LS032B7DD02 (336x536 pixels.)
* LS044Q7DH01 (320x240 pixels.)
*------------------------------------------------*/
#ifndef USE_SHARP_MIP
# define USE_SHARP_MIP 0
#endif
#if USE_SHARP_MIP
# define SHARP_MIP_HOR_RES LV_HOR_RES
# define SHARP_MIP_VER_RES LV_VER_RES
# define SHARP_MIP_SOFT_COM_INVERSION 0
# define SHARP_MIP_REV_BYTE(b) /*((uint8_t) __REV(__RBIT(b)))*/ /*Architecture / compiler dependent byte bits order reverse*/
#endif /*USE_SHARP_MIP*/
/*-------------------------------------------------
* ILI9341 240X320 TFT LCD
*------------------------------------------------*/
#ifndef USE_ILI9341
# define USE_ILI9341 0
#endif
#if USE_ILI9341
# define ILI9341_HOR_RES LV_HOR_RES
# define ILI9341_VER_RES LV_VER_RES
# define ILI9341_GAMMA 1
# define ILI9341_TEARING 0
#endif /*USE_ILI9341*/
/*-----------------------------------------
* Linux frame buffer device (/dev/fbx)
*-----------------------------------------*/
#ifndef USE_FBDEV
# define USE_FBDEV 0
#endif
#if USE_FBDEV
# define FBDEV_PATH "/dev/fb0"
#endif
/*-----------------------------------------
* FreeBSD frame buffer device (/dev/fbx)
*.........................................*/
#ifndef USE_BSD_FBDEV
# define USE_BSD_FBDEV 0
#endif
#if USE_BSD_FBDEV
# define FBDEV_PATH "/dev/fb0"
#endif
/*-----------------------------------------
* DRM/KMS device (/dev/dri/cardX)
*-----------------------------------------*/
#ifndef USE_DRM
# define USE_DRM 0
#endif
#if USE_DRM
# define DRM_CARD "/dev/dri/card0"
# define DRM_CONNECTOR_ID -1 /* -1 for the first connected one */
#endif
/*********************
* INPUT DEVICES
*********************/
/*--------------
* XPT2046
*--------------*/
#ifndef USE_XPT2046
# define USE_XPT2046 0
#endif
#if USE_XPT2046
# define XPT2046_HOR_RES 480
# define XPT2046_VER_RES 320
# define XPT2046_X_MIN 200
# define XPT2046_Y_MIN 200
# define XPT2046_X_MAX 3800
# define XPT2046_Y_MAX 3800
# define XPT2046_AVG 4
# define XPT2046_X_INV 0
# define XPT2046_Y_INV 0
# define XPT2046_XY_SWAP 0
#endif
/*-----------------
* FT5406EE8
*-----------------*/
#ifndef USE_FT5406EE8
# define USE_FT5406EE8 0
#endif
#if USE_FT5406EE8
# define FT5406EE8_I2C_ADR 0x38 /*7 bit address*/
#endif
/*---------------
* AD TOUCH
*--------------*/
#ifndef USE_AD_TOUCH
# define USE_AD_TOUCH 0
#endif
#if USE_AD_TOUCH
/*No settings*/
#endif
/*---------------------------------------
* Mouse or touchpad on PC (using SDL)
*-------------------------------------*/
/*DEPRECATED: Use the SDL driver instead. */
#ifndef USE_MOUSE
# define USE_MOUSE 0
#endif
#if USE_MOUSE
/*No settings*/
#endif
/*-------------------------------------------
* Mousewheel as encoder on PC (using SDL)
*------------------------------------------*/
/*DEPRECATED: Use the SDL driver instead. */
#ifndef USE_MOUSEWHEEL
# define USE_MOUSEWHEEL 0
#endif
#if USE_MOUSEWHEEL
/*No settings*/
#endif
/*-------------------------------------------------
* Touchscreen, mouse/touchpad or keyboard as libinput interface (for Linux based systems)
*------------------------------------------------*/
#ifndef USE_LIBINPUT
# define USE_LIBINPUT 0
#endif
#ifndef USE_BSD_LIBINPUT
# define USE_BSD_LIBINPUT 0
#endif
#if USE_LIBINPUT || USE_BSD_LIBINPUT
/*If only a single device of the same type is connected, you can also auto detect it, e.g.:
*#define LIBINPUT_NAME libinput_find_dev(LIBINPUT_CAPABILITY_TOUCH, false)*/
# define LIBINPUT_NAME "/dev/input/event0" /*You can use the "evtest" Linux tool to get the list of devices and test them*/
#endif /*USE_LIBINPUT || USE_BSD_LIBINPUT*/
/*-------------------------------------------------
* Mouse or touchpad as evdev interface (for Linux based systems)
*------------------------------------------------*/
#ifndef USE_EVDEV
# define USE_EVDEV 0
#endif
#ifndef USE_BSD_EVDEV
# define USE_BSD_EVDEV 0
#endif
#if USE_EVDEV || USE_BSD_EVDEV
# define EVDEV_NAME "/dev/input/event0" /*You can use the "evtest" Linux tool to get the list of devices and test them*/
# define EVDEV_SWAP_AXES 0 /*Swap the x and y axes of the touchscreen*/
# define EVDEV_CALIBRATE 0 /*Scale and offset the touchscreen coordinates by using maximum and minimum values for each axis*/
# if EVDEV_CALIBRATE
# define EVDEV_HOR_MIN 0 /*to invert axis swap EVDEV_XXX_MIN by EVDEV_XXX_MAX*/
# define EVDEV_HOR_MAX 4096 /*"evtest" Linux tool can help to get the correct calibraion values>*/
# define EVDEV_VER_MIN 0
# define EVDEV_VER_MAX 4096
# endif /*EVDEV_CALIBRATE*/
#endif /*USE_EVDEV*/
/*-------------------------------------------------
* Full keyboard support for evdev and libinput interface
*------------------------------------------------*/
# ifndef USE_XKB
# define USE_XKB 0
# endif
#if USE_LIBINPUT || USE_BSD_LIBINPUT || USE_EVDEV || USE_BSD_EVDEV
# if USE_XKB
# define XKB_KEY_MAP { .rules = NULL, \
.model = "pc101", \
.layout = "us", \
.variant = NULL, \
.options = NULL } /*"setxkbmap -query" can help find the right values for your keyboard*/
# endif /*USE_XKB*/
#endif /*USE_LIBINPUT || USE_BSD_LIBINPUT || USE_EVDEV || USE_BSD_EVDEV*/
/*-------------------------------
* Keyboard of a PC (using SDL)
*------------------------------*/
/*DEPRECATED: Use the SDL driver instead. */
#ifndef USE_KEYBOARD
# define USE_KEYBOARD 0
#endif
#if USE_KEYBOARD
/*No settings*/
#endif
#endif /*LV_DRV_CONF_H*/
#endif /*End of "Content enable"*/
+340
View File
@@ -0,0 +1,340 @@
#include <stdlib.h>
#include <unistd.h>
#define SDL_MAIN_HANDLED /*To fix SDL's "undefined reference to WinMain" \
issue*/
#include "demos/lv_demos.h"
#include "examples/lv_examples.h"
#include "sdl/sdl.h"
#include <SDL2/SDL.h>
#include <lvgl.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <luavgl.h>
#include "widgets/widgets.h"
typedef struct {
lua_State *L;
lv_obj_t *root;
} lua_context_t;
typedef struct {
lv_obj_t *root;
make_font_cb make_font;
delete_font_cb delete_font;
} luavgl_args_t;
/**
* Initialize the Hardware Abstraction Layer (HAL) for the LVGL graphics
* library
*/
static void hal_init(void)
{
/* Use the 'monitor' driver which creates window on PC's monitor to simulate a
* display*/
sdl_init();
/*Create a display buffer*/
static lv_disp_draw_buf_t disp_buf1;
static lv_color_t buf1_1[SDL_HOR_RES * SDL_VER_RES];
lv_disp_draw_buf_init(&disp_buf1, buf1_1, NULL, SDL_HOR_RES * SDL_VER_RES);
/*Create a display*/
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
disp_drv.draw_buf = &disp_buf1;
disp_drv.flush_cb = sdl_display_flush;
disp_drv.hor_res = SDL_HOR_RES;
disp_drv.ver_res = SDL_VER_RES;
lv_disp_t *disp = lv_disp_drv_register(&disp_drv);
lv_theme_t *th = lv_theme_default_init(
disp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED),
LV_THEME_DEFAULT_DARK, LV_FONT_DEFAULT);
lv_disp_set_theme(disp, th);
lv_group_t *g = lv_group_create();
lv_group_set_default(g);
/* Add the mouse as input device
* Use the 'mouse' driver which reads the PC's mouse*/
static lv_indev_drv_t indev_drv_1;
lv_indev_drv_init(&indev_drv_1); /*Basic initialization*/
indev_drv_1.type = LV_INDEV_TYPE_POINTER;
/*This function will be called periodically (by the library) to get the mouse
* position and state*/
indev_drv_1.read_cb = sdl_mouse_read;
lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);
static lv_indev_drv_t indev_drv_2;
lv_indev_drv_init(&indev_drv_2); /*Basic initialization*/
indev_drv_2.type = LV_INDEV_TYPE_KEYPAD;
indev_drv_2.read_cb = sdl_keyboard_read;
lv_indev_t *kb_indev = lv_indev_drv_register(&indev_drv_2);
lv_indev_set_group(kb_indev, g);
static lv_indev_drv_t indev_drv_3;
lv_indev_drv_init(&indev_drv_3); /*Basic initialization*/
indev_drv_3.type = LV_INDEV_TYPE_ENCODER;
indev_drv_3.read_cb = sdl_mousewheel_read;
lv_indev_t *enc_indev = lv_indev_drv_register(&indev_drv_3);
lv_indev_set_group(enc_indev, g);
/*Set a cursor for the mouse*/
LV_IMG_DECLARE(mouse_cursor_icon); /*Declare the image file.*/
lv_obj_t *cursor_obj =
lv_img_create(lv_scr_act()); /*Create an image object for the cursor */
lv_img_set_src(cursor_obj, &mouse_cursor_icon); /*Set the image source*/
lv_indev_set_cursor(mouse_indev,
cursor_obj); /*Connect the image object to the driver*/
}
/*
** Prints an error message, adding the program name in front of it
** (if present)
*/
static void l_message(const char *pname, const char *msg)
{
printf("%s: %s\n", pname ? pname : " ", msg);
}
/*
** Check whether 'status' is not OK and, if so, prints the error
** message on the top of the stack. It assumes that the error object
** is a string, as it was either generated by Lua or by 'msghandler'.
*/
static int report(lua_State *L, int status)
{
if (status != LUA_OK) {
const char *msg = lua_tostring(L, -1);
l_message("luactx", msg);
lua_pop(L, 1); /* remove message */
}
return status;
}
/*
** Message handler used to run all chunks
*/
static int msghandler(lua_State *L)
{
const char *msg = lua_tostring(L, 1);
if (msg == NULL) { /* is error object not a string? */
if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */
lua_type(L, -1) == LUA_TSTRING) /* that produces a string? */
return 1; /* that is the message */
else
msg = lua_pushfstring(L, "(error object is a %s value)",
luaL_typename(L, 1));
}
/* append a standard traceback */
luaL_traceback(L, L, msg, 1);
msg = lua_tostring(L, -1);
lua_pop(L, 1);
lv_obj_t *root = NULL;
luavgl_ctx_t *ctx = luavgl_context(L);
root = ctx->root ? ctx->root : lv_scr_act();
lv_obj_t *label = lv_label_create(root);
lv_label_set_text(label, msg);
lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP);
lv_obj_set_style_text_font(label, LV_FONT_DEFAULT, 0);
lv_obj_set_width(label, LV_PCT(80));
lv_obj_center(label);
printf("trace back: \n%s\n", msg);
return 0; /* return no trace, since we already processed it. */
}
static int lua_panic(lua_State *L)
{
printf("LUA panic:\n%s\n", lua_tostring(L, -1));
return 0; /* return to Lua to abort */
}
/*
** protected main entry
*/
static int pmain(lua_State *L)
{
int status;
const char *script = lua_tostring(L, 1);
luavgl_args_t *args = lua_touserdata(L, 2);
if (args == NULL || args->root == NULL) {
printf("Null root object.\n");
return 0;
}
luavgl_set_root(L, args->root);
luavgl_set_font_extension(L, args->make_font, args->delete_font);
/**
* Set global variable SCRIPT_PATH, to make image src path easier.
*/
char *path = strdup(script);
if (path == NULL) {
printf("no memory.\n");
return 0;
}
int i = strlen(path);
for (; i; i--) {
if (path[i] == '/') {
path[i + 1] = '\0';
break;
}
}
printf("script path: %s\n", path);
lua_pushstring(L, path);
lua_setglobal(L, "SCRIPT_PATH");
luaL_openlibs(L);
lua_getglobal(L, "package");
lua_getfield(L, -1, "path");
const char *pkg_path = lua_tostring(L, -1);
char *new_path = malloc(strlen(pkg_path) + strlen(script) + 2);
strcpy(new_path, pkg_path);
strcat(new_path, ";"), strcat(new_path, path), strcat(new_path, "?.lua");
lua_pop(L, 1);
lua_pushstring(L, new_path);
lua_setfield(L, -2, "path");
lua_pop(L, 1);
free(path);
free(new_path);
lua_atpanic(L, &lua_panic);
luaL_requiref(L, "lvgl", luaopen_lvgl, 1);
lua_pop(L, 1);
luavgl_widgets_init(L);
lua_pushcfunction(L, msghandler); /* push message handler */
int base = lua_gettop(L);
status = luaL_loadfile(L, script);
if (status != LUA_OK) {
lua_pushfstring(L, "failed to load: %s\n", script);
/* manually show the error to screen. */
lua_insert(L, 1);
msghandler(L);
return 0;
}
status = lua_pcall(L, 0, 0, base);
lua_remove(L, base); /* remove message handler from the stack */
report(L, status);
lua_pushboolean(L, 1); /* signal no errors */
return 1;
}
lua_context_t *lua_load_script(const char *script, luavgl_args_t *args)
{
int ret, status;
/* create the thread to run script. */
if (script == NULL) {
printf("args error.\n");
return NULL;
}
printf("run script: %s\n", script);
lua_State *L = luaL_newstate(); /* create state */
if (L == NULL) {
printf("no mem for lua state.\n");
return NULL;
}
lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */
lua_pushstring(L, script);
lua_pushlightuserdata(L, args);
status = lua_pcall(L, 2, 1, 0); /* do the call */
ret = lua_toboolean(L, -1);
report(L, status);
if (!ret || status != LUA_OK) {
/* This should never happen */
printf("pcall failed.\n");
lua_close(L);
return NULL;
}
/* script may fail, but we continue until page destoried. */
lua_context_t *luactx = calloc(sizeof(*luactx), 1);
if (luactx == NULL) {
printf("no memory.\n");
goto lua_exit;
}
luactx->L = L;
luactx->root = args->root;
return luactx;
lua_exit:
lua_close(L);
return NULL;
}
int lua_terminate(lua_context_t *luactx)
{
lua_State *L = luactx->L;
lua_close(L);
free(luactx);
return 0;
}
static lua_context_t *lua_ctx;
static luavgl_args_t args;
static void reload_cb(lv_event_t *e)
{
(void)e;
if (lua_ctx != NULL) {
lua_terminate(lua_ctx);
}
lua_ctx = lua_load_script(LUAVGL_EXAMPLE_DIR "/examples.lua", &args);
}
int main(int argc, char **argv)
{
(void)argc; /*Unused*/
(void)argv; /*Unused*/
/*Initialize LVGL*/
lv_init();
/*Initialize the HAL (display, input devices, tick) for LVGL*/
hal_init();
args.root = lv_scr_act();
lua_ctx = lua_load_script(LUAVGL_EXAMPLE_DIR "/examples.lua", &args);
lv_obj_t *btn = lv_btn_create(lv_layer_sys());
lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, 0, -50);
lv_obj_set_size(btn, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_style_pad_all(btn, 5, 0);
lv_obj_add_event_cb(btn, reload_cb, LV_EVENT_CLICKED, NULL);
lv_obj_t* label = lv_label_create(btn);
lv_label_set_text(label, "RELOAD");
lv_obj_center(label);
while (1) {
/* Periodically call the lv_task handler.
* It could be done in a timer interrupt or an OS task too.*/
lv_timer_handler();
usleep(5 * 1000);
}
return 0;
}
+104
View File
@@ -0,0 +1,104 @@
#include "lvgl.h"
const uint8_t mouse_cursor_icon_map[] = {
#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8
/*Pixel format: Alpha 8 bit, Red: 3 bit, Green: 3 bit, Blue: 2 bit*/
0x24, 0xb8, 0x24, 0xc8, 0x00, 0x13, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x49, 0xcc, 0xdb, 0xff, 0x49, 0xcc, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x49, 0xc8, 0xff, 0xff, 0xff, 0xff, 0x49, 0xe0, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x49, 0xcb, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x6d, 0xf3, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x49, 0xcb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0xff, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x49, 0xcb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0xff, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x49, 0xcb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xff, 0x24, 0xab, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x49, 0xcb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0x24, 0xbb, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x49, 0xcc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0x49, 0xd8, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00,
0x49, 0xcc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0xef, 0x00, 0x4f, 0x00, 0x00,
0x49, 0xcc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0xff, 0x00, 0x6b,
0x49, 0xcc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0x92, 0xf7, 0x92, 0xf8, 0x6e, 0xfb, 0x92, 0xf8, 0x6d, 0xff, 0x00, 0xb3,
0x49, 0xcc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0x24, 0xb7, 0x00, 0x1b, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x25, 0x07,
0x49, 0xcc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0xf0, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x49, 0xcc, 0xff, 0xff, 0xff, 0xff, 0x49, 0xd8, 0x00, 0x78, 0x92, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x6d, 0xd3, 0xff, 0xff, 0x6d, 0xef, 0x00, 0x34, 0x00, 0x00, 0x49, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0xdc, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
0x49, 0xe0, 0x6d, 0xff, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xff, 0x00, 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x00, 0x68, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x49, 0xd0, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x6d, 0xd8, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xb7, 0xff, 0xff, 0xff, 0x92, 0xff, 0x49, 0xac, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x25, 0xd7, 0x49, 0xc7, 0x00, 0x47, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
#endif
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0
/*Pixel format: Alpha 8 bit, Red: 5 bit, Green: 6 bit, Blue: 5 bit*/
0xc3, 0x18, 0xb8, 0xe4, 0x20, 0xc8, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x49, 0x4a, 0xcc, 0x96, 0xb5, 0xff, 0xc7, 0x39, 0xcc, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe7, 0x39, 0xc8, 0xbf, 0xff, 0xff, 0xfb, 0xde, 0xff, 0x28, 0x42, 0xe0, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe7, 0x39, 0xcb, 0x3d, 0xef, 0xff, 0xff, 0xff, 0xfc, 0x3d, 0xef, 0xff, 0xcb, 0x5a, 0xf3, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe7, 0x39, 0xcb, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x8e, 0x73, 0xff, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe8, 0x41, 0xcb, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x51, 0x8c, 0xff, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x9c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe8, 0x41, 0xcb, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, 0xa5, 0xff, 0xa2, 0x10, 0xab, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x42, 0xcb, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd7, 0xbd, 0xff, 0x04, 0x21, 0xbb, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x42, 0xcc, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 0xff, 0xe8, 0x41, 0xd8, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x42, 0xcc, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe6, 0xff, 0xab, 0x5a, 0xef, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
0x08, 0x42, 0xcc, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0xff, 0xaf, 0x7b, 0xff, 0x00, 0x00, 0x6b,
0x28, 0x42, 0xcc, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7a, 0xd6, 0xff, 0x10, 0x84, 0xf7, 0xae, 0x73, 0xf8, 0x6e, 0x73, 0xfb, 0x8e, 0x73, 0xf8, 0xcb, 0x5a, 0xff, 0x61, 0x08, 0xb3,
0x28, 0x42, 0xcc, 0x7d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 0xff, 0xa2, 0x10, 0xb7, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x14, 0x00, 0x00, 0x13, 0x00, 0x00, 0x0c, 0x45, 0x29, 0x07,
0x29, 0x4a, 0xcc, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xde, 0xff, 0xec, 0x62, 0xff, 0x1c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x63, 0xf0, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x29, 0x4a, 0xcc, 0xdf, 0xff, 0xff, 0x7d, 0xef, 0xff, 0x49, 0x4a, 0xd8, 0x00, 0x00, 0x78, 0x51, 0x8c, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x38, 0xc6, 0xff, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xcb, 0x5a, 0xd3, 0xdb, 0xde, 0xff, 0xec, 0x62, 0xef, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xc7, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0xff, 0xaa, 0x52, 0xdc, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0xe8, 0x41, 0xe0, 0xaa, 0x52, 0xff, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x72, 0x94, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x96, 0xb5, 0xff, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x61, 0x08, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x68, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x69, 0x4a, 0xd0, 0x7d, 0xef, 0xff, 0xff, 0xff, 0xfc, 0xbe, 0xf7, 0xff, 0xaa, 0x52, 0xd8, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x75, 0xad, 0xff, 0xbf, 0xff, 0xff, 0x10, 0x84, 0xff, 0x86, 0x31, 0xac, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x41, 0x08, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x66, 0x31, 0xd7, 0xc7, 0x39, 0xc7, 0x00, 0x00, 0x47, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
#endif
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP != 0
/*Pixel format: Alpha 8 bit, Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 color bytes are swapped*/
0x18, 0xc3, 0xb8, 0x20, 0xe4, 0xc8, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x4a, 0x49, 0xcc, 0xb5, 0x96, 0xff, 0x39, 0xc7, 0xcc, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x39, 0xe7, 0xc8, 0xff, 0xbf, 0xff, 0xde, 0xfb, 0xff, 0x42, 0x28, 0xe0, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x39, 0xe7, 0xcb, 0xef, 0x3d, 0xff, 0xff, 0xff, 0xfc, 0xef, 0x3d, 0xff, 0x5a, 0xcb, 0xf3, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x39, 0xe7, 0xcb, 0xef, 0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x73, 0x8e, 0xff, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x41, 0xe8, 0xcb, 0xef, 0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8c, 0x51, 0xff, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xd3, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x41, 0xe8, 0xcb, 0xef, 0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x14, 0xff, 0x10, 0xa2, 0xab, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x42, 0x08, 0xcb, 0xef, 0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbd, 0xd7, 0xff, 0x21, 0x04, 0xbb, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x42, 0x08, 0xcc, 0xef, 0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xce, 0x59, 0xff, 0x41, 0xe8, 0xd8, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x42, 0x08, 0xcc, 0xef, 0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe6, 0xfc, 0xff, 0x5a, 0xab, 0xef, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
0x42, 0x08, 0xcc, 0xef, 0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0xff, 0x7b, 0xaf, 0xff, 0x00, 0x00, 0x6b,
0x42, 0x28, 0xcc, 0xef, 0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd6, 0x7a, 0xff, 0x84, 0x10, 0xf7, 0x73, 0xae, 0xf8, 0x73, 0x6e, 0xfb, 0x73, 0x8e, 0xf8, 0x5a, 0xcb, 0xff, 0x08, 0x61, 0xb3,
0x42, 0x28, 0xcc, 0xef, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xce, 0x59, 0xff, 0x10, 0xa2, 0xb7, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x14, 0x00, 0x00, 0x13, 0x00, 0x00, 0x0c, 0x29, 0x45, 0x07,
0x4a, 0x29, 0xcc, 0xef, 0x5d, 0xff, 0xff, 0xff, 0xff, 0xde, 0xdb, 0xff, 0x62, 0xec, 0xff, 0xe7, 0x1c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x63, 0x0c, 0xf0, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x4a, 0x29, 0xcc, 0xff, 0xdf, 0xff, 0xef, 0x7d, 0xff, 0x4a, 0x49, 0xd8, 0x00, 0x00, 0x78, 0x8c, 0x51, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc6, 0x38, 0xff, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x5a, 0xcb, 0xd3, 0xde, 0xdb, 0xff, 0x62, 0xec, 0xef, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x39, 0xe7, 0xc7, 0xef, 0x5d, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0xff, 0x52, 0xaa, 0xdc, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x41, 0xe8, 0xe0, 0x52, 0xaa, 0xff, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x94, 0x72, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb5, 0x96, 0xff, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x08, 0x61, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x68, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x4a, 0x69, 0xd0, 0xef, 0x7d, 0xff, 0xff, 0xff, 0xfc, 0xf7, 0xbe, 0xff, 0x52, 0xaa, 0xd8, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe4, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xad, 0x75, 0xff, 0xff, 0xbf, 0xff, 0x84, 0x10, 0xff, 0x31, 0x86, 0xac, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x41, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x31, 0x66, 0xd7, 0x39, 0xc7, 0xc7, 0x00, 0x00, 0x47, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
#endif
#if LV_COLOR_DEPTH == 32
0x19, 0x19, 0x19, 0xb8, 0x1e, 0x1e, 0x1e, 0xc8, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x48, 0x48, 0x48, 0xcc, 0xb2, 0xb2, 0xb2, 0xff, 0x3a, 0x3a, 0x3a, 0xcc, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3b, 0x3b, 0x3b, 0xc8, 0xf6, 0xf6, 0xf6, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0x43, 0x43, 0x43, 0xe0, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3b, 0x3b, 0x3b, 0xcb, 0xe6, 0xe6, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe5, 0xe5, 0xe5, 0xff, 0x59, 0x59, 0x59, 0xf3, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3c, 0x3c, 0x3c, 0xcb, 0xe9, 0xe9, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0x72, 0x72, 0x72, 0xff, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3d, 0x3d, 0x3d, 0xcb, 0xe9, 0xe9, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8a, 0x8a, 0x8a, 0xff, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x99, 0x99, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3e, 0x3e, 0x3e, 0xcb, 0xe9, 0xe9, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa2, 0xa2, 0xa2, 0xff, 0x13, 0x13, 0x13, 0xab, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3f, 0x3f, 0x3f, 0xcb, 0xe9, 0xe9, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xb7, 0xb7, 0xff, 0x1f, 0x1f, 0x1f, 0xbb, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x41, 0x41, 0x41, 0xcc, 0xea, 0xea, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xca, 0xca, 0xca, 0xff, 0x3d, 0x3d, 0x3d, 0xd8, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x41, 0x41, 0x41, 0xcc, 0xea, 0xea, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xde, 0xde, 0xde, 0xff, 0x56, 0x56, 0x56, 0xef, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00,
0x42, 0x42, 0x42, 0xcc, 0xea, 0xea, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0x76, 0x76, 0x76, 0xff, 0x00, 0x00, 0x00, 0x6b,
0x43, 0x43, 0x43, 0xcc, 0xea, 0xea, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xce, 0xce, 0xce, 0xff, 0x80, 0x80, 0x80, 0xf7, 0x74, 0x74, 0x74, 0xf8, 0x6d, 0x6d, 0x6d, 0xfb, 0x72, 0x72, 0x72, 0xf8, 0x57, 0x57, 0x57, 0xff, 0x0c, 0x0c, 0x0c, 0xb3,
0x44, 0x44, 0x44, 0xcc, 0xeb, 0xeb, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfb, 0xfb, 0xfb, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0xc9, 0xc9, 0xff, 0x13, 0x13, 0x13, 0xb7, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0c, 0x29, 0x29, 0x29, 0x07,
0x45, 0x45, 0x45, 0xcc, 0xe8, 0xe8, 0xe8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd9, 0xd9, 0xd9, 0xff, 0x5e, 0x5e, 0x5e, 0xff, 0xe2, 0xe2, 0xe2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x62, 0x62, 0x62, 0xf0, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x45, 0x45, 0x45, 0xcc, 0xf9, 0xf9, 0xf9, 0xff, 0xec, 0xec, 0xec, 0xff, 0x4a, 0x4a, 0x4a, 0xd8, 0x00, 0x00, 0x00, 0x78, 0x8a, 0x8a, 0x8a, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xc3, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x58, 0x58, 0x58, 0xd3, 0xd9, 0xd9, 0xd9, 0xff, 0x5e, 0x5e, 0x5e, 0xef, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x3b, 0x3b, 0xc7, 0xe9, 0xe9, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0x54, 0x54, 0x54, 0xdc, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
0x3e, 0x3e, 0x3e, 0xe0, 0x54, 0x54, 0x54, 0xff, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x8e, 0x8e, 0x8e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb0, 0xb0, 0xb0, 0xff, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x4c, 0x4c, 0x4c, 0xd0, 0xec, 0xec, 0xec, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf4, 0xf4, 0xf4, 0xff, 0x53, 0x53, 0x53, 0xd8, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xab, 0xab, 0xab, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0x80, 0x80, 0x80, 0xff, 0x31, 0x31, 0x31, 0xac, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x09, 0x09, 0x09, 0x03, 0x02, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x2e, 0x2e, 0x2e, 0xd7, 0x38, 0x38, 0x38, 0xc7, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
#endif
};
lv_img_dsc_t mouse_cursor_icon = {
.header.always_zero = 0,
.header.w = 14,
.header.h = 20,
.data_size = 280 * LV_IMG_PX_SIZE_ALPHA_BYTE,
.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA,
.data = mouse_cursor_icon_map,
};
+113
View File
@@ -0,0 +1,113 @@
#include <lauxlib.h>
#include <lua.h>
#include <lvgl.h>
#include <stdlib.h>
#include <luavgl.h>
#include "lv_analog_time.h"
static int luavgl_analog_time_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_analog_time_create);
}
static void _lv_analog_time_set_hands(void *obj, lua_State *L)
{
if (!lua_istable(L, -1)) {
luaL_argerror(L, -1, "expect date table.");
return;
}
const void *hour, *minute, *second;
lua_getfield(L, -1, "hour");
hour = luavgl_toimgsrc(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "minute");
minute = luavgl_toimgsrc(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "second");
second = luavgl_toimgsrc(L, -1);
lua_pop(L, 1);
lv_analog_time_set_hands(obj, hour, minute, second);
}
/* clang-format off */
static const luavgl_value_setter_t analog_time_property_table[] = {
{"hands", SETTER_TYPE_STACK, {.setter_stack = _lv_analog_time_set_hands}},
{"period", SETTER_TYPE_INT, {.setter = (setter_int_t)lv_analog_time_set_period}},
};
/* clang-format on */
static int luavgl_analog_time_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, analog_time_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_obj_set_property_kv(L, obj);
if (ret != 0) {
printf("unkown property for analog_time: %s\n", lua_tostring(L, -2));
}
return -1;
}
static int luavgl_analog_time_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_iterate(L, -1, luavgl_analog_time_set_property_kv, obj);
return 0;
}
static int luavgl_analog_time_pause(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_analog_time_pause(obj);
return 0;
}
static int luavgl_analog_time_resume(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_analog_time_resume(obj);
return 0;
}
static const luaL_Reg luavgl_analog_time_methods[] = {
{"set", luavgl_analog_time_set },
{"pause", luavgl_analog_time_pause },
{"resume", luavgl_analog_time_resume},
{NULL, NULL },
};
void luavgl_analog_time_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_analog_time_class, "lv_analog_time",
luavgl_analog_time_methods);
lua_pop(L, 1);
luaL_getmetatable(L, "widgets");
lua_getfield(L, -1, "__index");
lua_pushcfunction(L, luavgl_analog_time_create);
lua_setfield(L, -2, "AnalogTime");
lua_pop(L, 2);
}
+69
View File
@@ -0,0 +1,69 @@
#include <lauxlib.h>
#include <lua.h>
#include <lvgl.h>
#include <stdlib.h>
#include <luavgl.h>
static int luavgl_extension_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_obj_create);
}
/* clang-format off */
static const luavgl_value_setter_t extension_property_table[] = {
{"dummy", SETTER_TYPE_STACK, {.setter_stack = _lv_dummy_set}},
};
/* clang-format on */
static int luavgl_extension_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, extension_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_obj_set_property_kv(L, obj);
if (ret != 0) {
printf("unkown property for extension.\n");
}
return ret;
}
static int luavgl_extension_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_iterate(L, -1, luavgl_extension_set_property_kv, obj);
return 0;
}
static const luaL_Reg luavgl_extension_methods[] = {
{"set", luavgl_extension_set},
{NULL, NULL},
};
void luavgl_extension_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_btn_class, "lv_extension",
luavgl_extension_methods);
lua_pop(L, 1);
luaL_getmetatable(L, "widgets");
lua_getfield(L, -1, "__index");
lua_pushcfunction(L, luavgl_extension_create);
lua_setfield(L, -2, "Extension");
lua_pop(L, 2);
}
@@ -0,0 +1,253 @@
/*********************
* INCLUDES
*********************/
#include "lv_analog_time.h"
#include "lv_pointer.h"
#include <time.h>
#if LV_USE_ANALOG_TIME
/*********************
* DEFINES
*********************/
#define MY_CLASS &lv_analog_time_class
#define UNIT_ONE_SECOND (1000)
#define UNIT_ONE_MINUTE (60 * UNIT_ONE_SECOND)
#define UNIT_ONE_HOUR (60 * UNIT_ONE_MINUTE)
#define UNIT_ONE_DAY (24 * UNIT_ONE_HOUR)
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_analog_time_constructor(const lv_obj_class_t* class_p,
lv_obj_t* obj);
static void lv_analog_time_destructor(const lv_obj_class_t* class_p,
lv_obj_t* obj);
static void update_time(lv_obj_t* obj);
static void timer_cb(lv_timer_t* timer);
static lv_obj_t* create_hand(lv_obj_t* obj, const char* img);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_analog_time_class = {
.constructor_cb = lv_analog_time_constructor,
.destructor_cb = lv_analog_time_destructor,
.instance_size = sizeof(lv_analog_time_t),
.base_class = &lv_obj_class,
};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_obj_t* lv_analog_time_create(lv_obj_t* parent)
{
lv_obj_t* obj = lv_obj_class_create_obj(MY_CLASS, parent);
lv_obj_class_init_obj(obj);
return obj;
}
void lv_analog_time_set_hands(lv_obj_t* obj, const void* hour,
const void* minute, const void* second)
{
lv_analog_time_t* analog = (lv_analog_time_t*)obj;
uint32_t period = UNIT_ONE_MINUTE; /* default */
/* remove hand if it's null */
if (analog->second) {
lv_obj_del(analog->second);
analog->second = NULL;
}
if (analog->minute) {
lv_obj_del(analog->minute);
analog->minute = NULL;
}
if (analog->hour) {
lv_obj_del(analog->hour);
analog->hour = NULL;
}
/* create hand if not null */
if (hour) {
analog->hour = create_hand(obj, hour);
/* for hour, we use minute as unit*/
lv_pointer_set_range(analog->hour, 0, 24 * 60, 0, 3600 * 2);
/* update period should be faster than 1minute(default) */
}
if (minute) {
analog->minute = create_hand(obj, minute);
/* for minute, update per second */
lv_pointer_set_range(analog->minute, 0, 60 * 60, 0, 3600);
/* update period should be faster than 1second */
if (period > 1 * UNIT_ONE_SECOND) {
period = UNIT_ONE_SECOND;
}
}
if (second) {
analog->second = create_hand(obj, second);
/* update per second */
lv_pointer_set_range(analog->second, 0, 60 * UNIT_ONE_SECOND, 0, 3600);
/* update period should be faster than 1second */
if (period > 1 * UNIT_ONE_SECOND) {
period = UNIT_ONE_SECOND;
}
}
if (period < analog->period)
analog->period = period;
if (analog->hour || analog->minute || analog->second) {
lv_timer_resume(analog->timer);
} else {
/* no more needed */
lv_timer_pause(analog->timer);
}
update_time(obj);
}
void lv_analog_time_pause(lv_obj_t* obj)
{
lv_analog_time_t* analog = (lv_analog_time_t*)obj;
lv_timer_pause(analog->timer);
}
void lv_analog_time_resume(lv_obj_t* obj)
{
lv_analog_time_t* analog = (lv_analog_time_t*)obj;
lv_timer_resume(analog->timer);
update_time(obj);
}
void lv_analog_time_set_period(lv_obj_t* obj, uint32_t period)
{
lv_analog_time_t* analog = (lv_analog_time_t*)obj;
analog->period = period;
lv_timer_set_period(analog->timer, period);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void lv_analog_time_constructor(const lv_obj_class_t* class_p,
lv_obj_t* obj)
{
LV_UNUSED(class_p);
LV_TRACE_OBJ_CREATE("begin");
lv_analog_time_t* analog = (lv_analog_time_t*)obj;
analog->period = 60 * 60 * 1000; /* default to 1Hour = 60min*60sec*1000ms*/
lv_obj_add_flag(lv_obj_get_parent(obj), LV_OBJ_FLAG_OVERFLOW_VISIBLE);
/* hands pivot is place to 0, 0 */
lv_obj_remove_style_all(obj);
lv_obj_set_size(obj, 0, 0);
analog->timer = lv_timer_create(timer_cb, UNIT_ONE_MINUTE, obj);
lv_timer_pause(analog->timer);
LV_TRACE_OBJ_CREATE("finished");
}
static void lv_analog_time_destructor(const lv_obj_class_t* class_p,
lv_obj_t* obj)
{
lv_analog_time_t* analog = (lv_analog_time_t*)obj;
lv_timer_del(analog->timer);
}
static lv_obj_t* create_hand(lv_obj_t* obj, const char* img)
{
lv_obj_t* hand;
hand = lv_pointer_create(obj);
lv_img_set_src(hand, img);
lv_point_t pivot;
lv_img_get_pivot(hand, &pivot);
/* we position the hand using image's center */
lv_obj_set_pos(hand, -pivot.x, -pivot.y);
return hand;
}
static void update_time(lv_obj_t* obj)
{
int value;
struct timespec ts;
struct tm* time;
int ret;
ret = clock_gettime(CLOCK_REALTIME, &ts);
if (ret != 0) {
LV_LOG_ERROR("get real time failed");
return;
}
time = localtime(&ts.tv_sec);
if (time == NULL) {
LV_LOG_ERROR("get local time failed");
return;
}
lv_analog_time_t* analog = (lv_analog_time_t*)obj;
value = time->tm_sec * 1000;
if (analog->period < UNIT_ONE_SECOND) {
/* sub-second update mode */
value += ts.tv_nsec / 1000000; /* add ms part */
}
if (analog->second)
lv_pointer_set_value(analog->second, value);
if (analog->minute)
lv_pointer_set_value(analog->minute, time->tm_min * 60 + time->tm_sec);
if (analog->hour)
lv_pointer_set_value(analog->hour, time->tm_hour * 60 + time->tm_min);
}
static void timer_cb(lv_timer_t* t)
{
/* timeup */
update_time(t->user_data);
}
/* examples */
#if 0
void lv_analog_time_example(void)
{
lv_obj_t* scr = lv_scr_act();
lv_obj_t* analog = lv_analog_time_create(scr);
lv_obj_center(analog);
lv_analog_time_set_hands(analog, "/data/hand-second.png", "/data/hand-second.png", "/data/hand-second.png");
lv_analog_time_set_period(analog, 60);
}
#endif
#endif
@@ -0,0 +1,64 @@
#ifndef LV_WIDGETS_ANALOG_TIME_H_
#define LV_WIDGETS_ANALOG_TIME_H_
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <lvgl.h>
#if LV_USE_ANALOG_TIME
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_obj_t obj;
lv_obj_t* hour;
lv_obj_t* minute;
lv_obj_t* second;
uint32_t period;
lv_timer_t* timer;
} lv_analog_time_t;
extern const lv_obj_class_t lv_analog_time_class;
/**********************
* GLOBAL PROTOTYPES
**********************/
lv_obj_t* lv_analog_time_create(lv_obj_t* parent);
/**
* Set images for hands of hour, minute and second.
* If specified hands image is NULL, then it's deleted.
*
* @note for simplicity, image pivot is set to image center.
*/
void lv_analog_time_set_hands(lv_obj_t* obj, const void* hour,
const void* minute, const void* second);
void lv_analog_time_pause(lv_obj_t* obj);
void lv_analog_time_resume(lv_obj_t* obj);
void lv_analog_time_set_period(lv_obj_t* obj, uint32_t period);
/**********************
* MACROS
**********************/
#endif /* */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* LV_WIDGETS_ANALOG_TIME_H_ */
+138
View File
@@ -0,0 +1,138 @@
/*********************
* INCLUDES
*********************/
#include "lv_pointer.h"
#if LV_USE_POINTER
/*********************
* DEFINES
*********************/
#define MY_CLASS &lv_pointer_class
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_pointer_constructor(const lv_obj_class_t* class_p,
lv_obj_t* obj);
static void angle_update(lv_obj_t* obj);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_pointer_class = {
.constructor_cb = lv_pointer_constructor,
.instance_size = sizeof(lv_pointer_t),
.base_class = &lv_img_class,
};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_obj_t* lv_pointer_create(lv_obj_t* parent)
{
lv_obj_t* obj = lv_obj_class_create_obj(MY_CLASS, parent);
lv_obj_class_init_obj(obj);
/* pointer can rotate out of parent's area. */
lv_obj_add_flag(parent, LV_OBJ_FLAG_OVERFLOW_VISIBLE);
return obj;
}
void lv_pointer_set_value(lv_obj_t* obj, int value)
{
lv_pointer_t* pointer = (lv_pointer_t*)obj;
if (pointer->value == value) {
return;
}
pointer->value = value;
angle_update(obj);
}
void lv_pointer_set_range(lv_obj_t* obj, int value_start, int value_range,
int angle_start, int angle_range)
{
lv_pointer_t* pointer = (lv_pointer_t*)obj;
pointer->value_start = value_start;
pointer->value_range = value_range;
pointer->angle_start = angle_start;
pointer->angle_range = angle_range;
/* update angle */
angle_update(obj);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void lv_pointer_constructor(const lv_obj_class_t* class_p,
lv_obj_t* obj)
{
LV_UNUSED(class_p);
LV_TRACE_OBJ_CREATE("begin");
lv_pointer_t* pointer = (lv_pointer_t*)obj;
/* set default range parameters */
pointer->angle_start = 0;
pointer->angle_range = 360 * 10;
pointer->value_start = 0;
pointer->value_range = 100;
LV_TRACE_OBJ_CREATE("finished");
}
static void angle_update(lv_obj_t* obj)
{
lv_pointer_t* pointer = (lv_pointer_t*)obj;
int angle = 0;
int value = pointer->value;
int value_start = pointer->value_start;
int value_range = pointer->value_range;
int angle_start = pointer->angle_start;
int angle_range = pointer->angle_range;
if (value_range != 0) {
/* Check value overflow, overwrite angle if so. */
int delta = value - value_start;
angle = angle_start;
angle += (delta * angle_range) / value_range;
/* check overflow */
if (value_range > 0) {
if (delta > value_range)
angle = angle_start + angle_range;
else if (value < value_start)
angle = angle_start;
} else { /* case of value_range < 0 */
if (delta < value_range)
angle = angle_start + angle_range;
else if (value > value_start)
angle = angle_start;
}
while (angle >= 3600)
angle -= 3600;
while (angle < 0)
angle += 3600;
}
if (angle == lv_img_get_angle(obj)) {
/* not changed */
return;
}
lv_img_set_angle(obj, angle);
}
#endif
+67
View File
@@ -0,0 +1,67 @@
#ifndef LV_WIDGETS_POINTER_H_
#define LV_WIDGETS_POINTER_H_
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <lvgl.h>
#if LV_USE_POINTER
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_img_t obj;
int value;
int value_start;
int value_range;
int angle_start;
int angle_range;
} lv_pointer_t;
extern const lv_obj_class_t lv_pointer_class;
/**********************
* GLOBAL PROTOTYPES
**********************/
lv_obj_t* lv_pointer_create(lv_obj_t* parent);
/**
* Set range parameters for pointer
* @param value_start the value mapped to angle_start
* @param value_range the value range, could be negative
* @param angle_start the angle will be set then value equals to value_start
* @param angle_range the angle range, could be negative
*/
void lv_pointer_set_range(lv_obj_t* obj, int value_start, int value_range,
int angle_start, int angle_range);
/**
* Set current value pointer points to
* @param value If value is out of range, then angle is also clampped to limits
*/
void lv_pointer_set_value(lv_obj_t* obj, int value);
/**********************
* MACROS
**********************/
#endif /* */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* LV_WIDGETS_POINTER_H_ */
+101
View File
@@ -0,0 +1,101 @@
#include <lauxlib.h>
#include <lua.h>
#include <lvgl.h>
#include <stdlib.h>
#include <luavgl.h>
#include "lv_pointer.h"
static int luavgl_pointer_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_pointer_create);
}
static void _lv_pointer_set_range(void *obj, lua_State *L)
{
if (!lua_istable(L, -1)) {
luaL_argerror(L, -1, "expect date table.");
return;
}
uint32_t value_start, value_range, angle_start, angle_range;
lua_getfield(L, -1, "valueStart");
value_start = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "valueRange");
value_range = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "angleStart");
angle_start = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "angleRange");
angle_range = lua_tointeger(L, -1);
lua_pop(L, 1);
lv_pointer_set_range(obj, value_start, value_range, angle_start,
angle_range);
}
/* clang-format off */
static const luavgl_value_setter_t pointer_property_table[] = {
{"range", SETTER_TYPE_STACK, {.setter_stack = _lv_pointer_set_range}},
{"value", SETTER_TYPE_INT, {.setter = (setter_int_t)lv_pointer_set_value}},
};
/* clang-format on */
static int luavgl_pointer_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, pointer_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_img_set_property_kv(L, obj);
if (ret != 0) {
printf("unkown property for pointer: %s\n", lua_tostring(L, -2));
}
return -1;
}
static int luavgl_pointer_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_iterate(L, -1, luavgl_pointer_set_property_kv, obj);
return 0;
}
static const luaL_Reg luavgl_pointer_methods[] = {
{"set", luavgl_pointer_set},
{NULL, NULL },
};
void luavgl_pointer_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_pointer_class, "lv_pointer",
luavgl_pointer_methods);
lua_pop(L, 1);
luaL_getmetatable(L, "widgets");
lua_getfield(L, -1, "__index");
lua_pushcfunction(L, luavgl_pointer_create);
lua_setfield(L, -2, "Pointer");
lua_pop(L, 2);
}
+8
View File
@@ -0,0 +1,8 @@
#include "widgets.h"
void luavgl_widgets_init(lua_State *L)
{
luavgl_extension_init(L);
luavgl_pointer_init(L);
luavgl_analog_time_init(L);
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef WIDGETS_WIDGETS_H_
#define WIDGETS_WIDGETS_H_
#include <lua.h>
void luavgl_extension_init(lua_State *L);
void luavgl_pointer_init(lua_State *L);
void luavgl_analog_time_init(lua_State *L);
void luavgl_widgets_init(lua_State *L);
#endif /* WIDGETS_WIDGETS_H_ */
+104
View File
@@ -0,0 +1,104 @@
---@meta
lvgl = require "lvgl"
---
--- Create Extension widget on parent
--- @param parent? Object | nil
--- @param property? ObjectStyle
--- @return Extension
function lvgl.Extension(parent, property)
end
--- Create Extension widget on obj
--- @param property? ObjectStyle
--- @return Extension
function obj:Extension(property)
end
---
--- Extension widget
---@class Extension:Object
---
local extension = {}
--- set method
--- @param p ObjectStyle
--- @return nil
function extension:set(p)
end
---
--- Create Pointer widget
--- @param parent? Object | nil
--- @param property? ObjectStyle
--- @return Pointer
function lvgl.Pointer(parent, property)
end
--- Create Extension widget on obj
--- @param property? ObjectStyle
--- @return Extension
function obj:Pointer(property)
end
---
--- Pointer widget
---@class Pointer:Object
---
local pointer = {}
--- set method
--- @param p ObjectStyle
--- @return nil
function pointer:set(p)
end
---
--- Create AnalogTime widget on parent
--- @param parent? Object | nil
--- @param property? AnalogTimeStyle
--- @return AnalogTime
function lvgl.AnalogTime(parent, property)
end
--- Create AnalogTime widget on obj
--- @param property? AnalogTimeStyle
--- @return AnalogTime
function obj:AnalogTime(property)
end
---
--- Extension widget
---@class AnalogTime:Object
---
local analogTime = {}
--- set method
--- @param p AnalogTimeStyle
--- @return nil
function analogTime:set(p)
end
--- Pause the hand refresh timer
function analogTime:pause()
end
--- Resume the hand refresh timer
function analogTime:resume()
end
--- Analog time hands parameter
--- @class AnalogTimeHands
--- @field hour string Image source path for hour hand
--- @field minute string minute hand
--- @field second string second hand
---
--- Analog time widget property
--- @class AnalogTimeStyle :StyleProp
--- @field hands AnalogTimeHands Hands images
--- @field period integer Timer refresh period, default to 1s/1min depending on whether there's second/min hands
---
+339
View File
@@ -0,0 +1,339 @@
#include "luavgl.h"
#include "private.h"
/**
* Different to lvgl anim, anim in lua can be restarted after it's done.
* anim.stop()
* anim.start()
* anim.delete() this will mark anim as no longer needed and waiting for gc.
*/
typedef struct luavgl_anim_s {
lua_State *L;
lv_anim_t *aa; /* the handler returns be lv_anim_start */
lv_anim_t cfg; /* the configuration, must not be the first element. */
int obj_ref; /* the object used for animation, used as in exec_cb */
int exec_cb;
int done_cb;
int self_ref; /* ref in registry to this anim */
bool deleted; /* manually deleted from lua */
} luavgl_anim_t;
typedef luavgl_anim_t *luavgl_anim_handle_t;
static luavgl_anim_t *luavgl_check_anim(lua_State *L, int index)
{
luavgl_anim_t *a = luaL_checkudata(L, index, "lv_anim");
if (a->deleted) {
luaL_argerror(L, index, "anim already deleted.");
return NULL;
}
return a;
}
static void luavgl_anim_exec_cb(void *var, int32_t value)
{
luavgl_anim_t *a = var;
lua_State *L = a->L;
if (a->exec_cb == LUA_NOREF || a->obj_ref == LUA_NOREF) {
debug("anim error, callback or obj not found.\n");
luaL_error(L, "anim founds no callback or obj.");
return;
}
/* stack: 1. function, 2. obj-userdata, 3. value */
lua_rawgeti(L, LUA_REGISTRYINDEX, a->exec_cb);
lua_rawgeti(L, LUA_REGISTRYINDEX, a->obj_ref);
lua_pushinteger(L, value);
luavgl_pcall_int(L, 2, 0);
}
/* callback when anim is deleted by lvgl */
static void luavgl_anim_delete_cb(lv_anim_t *_a)
{
luavgl_anim_t *a = _a->var;
a->aa = NULL; /* handler deleted by lvgl */
lua_State *L = a->L;
if (a->done_cb != LUA_NOREF) {
/* stack: 1. function, 2. this anim, 3. obj-userdata */
lua_rawgeti(L, LUA_REGISTRYINDEX, a->done_cb);
lua_rawgeti(L, LUA_REGISTRYINDEX, a->self_ref);
lua_rawgeti(L, LUA_REGISTRYINDEX, a->obj_ref);
luavgl_pcall_int(L, 2, 0);
}
/* it's paused or deleted, thus can be gc'ed */
luaL_unref(L, LUA_REGISTRYINDEX, a->self_ref);
a->self_ref = LUA_NOREF;
}
static void _lv_anim_set_start_value(lv_anim_t *a, int32_t v)
{
a->start_value = v;
}
static void _lv_anim_set_end_value(lv_anim_t *a, int32_t v)
{
a->end_value = v;
}
static void _lv_anim_set_path(void *obj, lua_State *L)
{
lv_anim_t *a = obj;
const char *path = NULL;
if (lua_isstring(L, -1)) {
path = lua_tostring(L, -1);
}
a->path_cb = lv_anim_path_linear;
if (path == NULL || strcmp(path, "linear") == 0) {
; /* use default linear path */
} else if (strcmp(path, "ease_in") == 0) {
a->path_cb = lv_anim_path_ease_in;
} else if (strcmp(path, "ease_out") == 0) {
a->path_cb = lv_anim_path_ease_out;
} else if (strcmp(path, "ease_in_out") == 0) {
a->path_cb = lv_anim_path_ease_in_out;
} else if (strcmp(path, "overshoot") == 0) {
a->path_cb = lv_anim_path_overshoot;
} else if (strcmp(path, "bounce") == 0) {
a->path_cb = lv_anim_path_bounce;
} else if (strcmp(path, "step") == 0) {
a->path_cb = lv_anim_path_step;
}
}
/* clang-format off */
static const luavgl_value_setter_t anim_property_table[] = {
{ "run", SETTER_TYPE_STACK, { .setter_stack = _lv_dummy_set } },
{ "start_value", 0, { .setter = (setter_int_t)_lv_anim_set_start_value } },
{ "end_value", 0, { .setter = (setter_int_t)_lv_anim_set_end_value } },
{ "time", 0, { .setter = (setter_int_t)lv_anim_set_time } },
{ "duration", 0, { .setter = (setter_int_t)lv_anim_set_time } },
{ "delay", 0, { .setter = (setter_int_t)lv_anim_set_delay } },
{ "repeat_count", 0, { .setter = (setter_int_t)lv_anim_set_repeat_count } },
{ "repeat_delay", 0, { .setter = (setter_int_t)lv_anim_set_repeat_delay } },
{ "early_apply", 0, { .setter = (setter_int_t)lv_anim_set_early_apply } },
{ "playback_time", 0, { .setter = (setter_int_t)lv_anim_set_playback_time } },
{ "playback_delay", 0, { .setter = (setter_int_t)lv_anim_set_playback_delay } },
{ "path", SETTER_TYPE_STACK, { .setter_stack = _lv_anim_set_path } },
{ "exec_cb", SETTER_TYPE_STACK, { .setter_stack = _lv_dummy_set } },
};
/* clang-format on */
static int anim_set_para_cb(lua_State *L, void *data)
{
int ret = luavgl_set_property(L, data, anim_property_table);
if (ret != 0) {
debug("failed\n");
}
return ret;
}
static int luavgl_anim_stop(lua_State *L)
{
luavgl_anim_t *a = luavgl_check_anim(L, 1);
if (a->aa == NULL || a->self_ref == LUA_NOREF) {
debug("already stopped");
return 0;
}
lv_anim_del(a, luavgl_anim_exec_cb);
/* work done in luavgl_anim_delete_cb */
return 0;
}
static int luavgl_anim_delete(lua_State *L)
{
luavgl_anim_stop(L);
luavgl_anim_t *a = luavgl_check_anim(L, 1);
/* object and callbacks can be gc'ed now */
luaL_unref(L, LUA_REGISTRYINDEX, a->done_cb);
luaL_unref(L, LUA_REGISTRYINDEX, a->exec_cb);
luaL_unref(L, LUA_REGISTRYINDEX, a->obj_ref);
luaL_unref(L, LUA_REGISTRYINDEX, a->self_ref);
a->done_cb = LUA_NOREF;
a->exec_cb = LUA_NOREF;
a->obj_ref = LUA_NOREF;
a->self_ref = LUA_NOREF;
a->deleted = true;
return 0;
}
static int luavgl_anim_start(lua_State *L)
{
luavgl_anim_t *a = luavgl_check_anim(L, 1);
if (a->aa) {
debug("we have an anim ongoing, stop it.");
luavgl_anim_stop(L);
}
lv_anim_t *new_a = lv_anim_start(&a->cfg);
a->aa = new_a;
debug("anim %p, aa: %p\n", a, a->aa);
if (a->self_ref == LUA_NOREF) {
/* it's started, thus cannot be gc'ed */
lua_pushvalue(L, 1);
a->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}
return 1;
}
/**
* anim:set { para }
* update anim parameter, stop anim if it's ongoing.
*/
static int luavgl_anim_set(lua_State *L)
{
luavgl_anim_t *a = luavgl_check_anim(L, 1);
if (a->aa) {
luavgl_anim_stop(L);
}
/* update anim parameters */
lv_anim_t *cfg = &a->cfg;
lua_getfield(L, 2, "exec_cb");
if (!lua_isnoneornil(L, -1)) {
luaL_unref(L, LUA_REGISTRYINDEX, a->exec_cb);
a->exec_cb = luavgl_check_continuation(L, -1);
}
lua_pop(L, 1);
lua_getfield(L, 2, "done_cb");
if (!lua_isnoneornil(L, -1)) {
luaL_unref(L, LUA_REGISTRYINDEX, a->done_cb);
a->done_cb = luavgl_check_continuation(L, -1);
}
lua_pop(L, 1);
lua_getfield(L, 2, "run");
bool run = lua_toboolean(L, -1);
lua_pop(L, 1);
luavgl_iterate(L, 2, anim_set_para_cb, cfg);
if (run) {
luavgl_anim_start(L);
}
return 1;
}
/**
* a = obj:Anim({anim parameters})
* a = obj:Anim{anim parameters}
* a = lvgl.Anim(var, anim_para)
*
* a:start()
*/
static int luavgl_anim_create(lua_State *L)
{
if (lua_isnoneornil(L, 1)) {
return luaL_argerror(L, 1, "anim var must not be nil or none.");
}
if (!lua_istable(L, 2)) {
return luaL_argerror(L, 2, "expect anim para table.");
}
luavgl_anim_t *a = lua_newuserdata(L, sizeof(luavgl_anim_t));
luaL_getmetatable(L, "lv_anim");
lua_setmetatable(L, -2);
lua_pushvalue(L, 1);
a->obj_ref = luaL_ref(L, LUA_REGISTRYINDEX);
a->exec_cb = LUA_NOREF;
a->done_cb = LUA_NOREF;
a->self_ref = LUA_NOREF;
a->aa = NULL;
a->L = L;
a->deleted = false;
lv_anim_t *cfg = &a->cfg;
lv_anim_init(cfg);
cfg->var = a;
cfg->deleted_cb = luavgl_anim_delete_cb;
cfg->exec_cb = luavgl_anim_exec_cb;
/* leave only anim userdata and para table on stack */
lua_remove(L, 1); /* para, anim */
lua_insert(L, 1); /* anim, para */
luavgl_anim_set(L);
lua_pop(L, 1); /* anim */
debug("create anim: %p, aa: %p\n", a, a->aa);
return 1;
}
static int luavgl_anim_gc(lua_State *L)
{
debug("\n");
luavgl_anim_t *a = luaL_checkudata(L, 1, "lv_anim");
if (a->deleted)
return 0;
luavgl_anim_delete(L);
return 0;
}
static int luavgl_anim_tostring(lua_State *L)
{
luavgl_anim_t *a = luavgl_check_anim(L, -1);
lua_pushfstring(
L, "anim %p: %s, value: [%d..%d], current: %d, repeat_cnt: %d", a->aa,
a->aa ? "running" : "stopped", a->cfg.start_value, a->cfg.end_value,
a->aa ? a->aa->current_value : -1, a->cfg.repeat_cnt);
return 1;
}
static const luaL_Reg luavgl_anim_meta[] = {
{"__gc", luavgl_anim_gc },
{"__tostring", luavgl_anim_tostring},
{"__index", NULL }, /* place holder */
{NULL, NULL },
};
static const luaL_Reg luavgl_anim_methods[] = {
{"set", luavgl_anim_set },
{"start", luavgl_anim_start },
/* in lua anim, stopped anim can be restarted. */
{"stop", luavgl_anim_stop },
{"delete", luavgl_anim_delete},
{NULL, NULL }
};
static void luavgl_anim_init(lua_State *L)
{
/* create metatable */
luaL_newmetatable(L, "lv_anim");
luaL_setfuncs(L, luavgl_anim_meta, 0);
luaL_newlib(L, luavgl_anim_methods);
lua_setfield(L, -2, "__index");
lua_pop(L, 1); /* pop metatable */
}
+554
View File
@@ -0,0 +1,554 @@
#include "private.h"
/* clang-format off */
static void luavgl_event_code_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "ALL"); lua_pushinteger(L, LV_EVENT_ALL); lua_settable(L, -3);
lua_pushstring(L, "PRESSED"); lua_pushinteger(L, LV_EVENT_PRESSED); lua_settable(L, -3);
lua_pushstring(L, "PRESSING"); lua_pushinteger(L, LV_EVENT_PRESSING); lua_settable(L, -3);
lua_pushstring(L, "PRESS_LOST"); lua_pushinteger(L, LV_EVENT_PRESS_LOST); lua_settable(L, -3);
lua_pushstring(L, "SHORT_CLICKED"); lua_pushinteger(L, LV_EVENT_SHORT_CLICKED); lua_settable(L, -3);
lua_pushstring(L, "LONG_PRESSED"); lua_pushinteger(L, LV_EVENT_LONG_PRESSED); lua_settable(L, -3);
lua_pushstring(L, "LONG_PRESSED_REPEAT"); lua_pushinteger(L, LV_EVENT_LONG_PRESSED_REPEAT); lua_settable(L, -3);
lua_pushstring(L, "CLICKED"); lua_pushinteger(L, LV_EVENT_CLICKED); lua_settable(L, -3);
lua_pushstring(L, "RELEASED"); lua_pushinteger(L, LV_EVENT_RELEASED); lua_settable(L, -3);
lua_pushstring(L, "SCROLL_BEGIN"); lua_pushinteger(L, LV_EVENT_SCROLL_BEGIN); lua_settable(L, -3);
lua_pushstring(L, "SCROLL_END"); lua_pushinteger(L, LV_EVENT_SCROLL_END); lua_settable(L, -3);
lua_pushstring(L, "SCROLL"); lua_pushinteger(L, LV_EVENT_SCROLL); lua_settable(L, -3);
lua_pushstring(L, "GESTURE"); lua_pushinteger(L, LV_EVENT_GESTURE); lua_settable(L, -3);
lua_pushstring(L, "KEY"); lua_pushinteger(L, LV_EVENT_KEY); lua_settable(L, -3);
lua_pushstring(L, "FOCUSED"); lua_pushinteger(L, LV_EVENT_FOCUSED); lua_settable(L, -3);
lua_pushstring(L, "DEFOCUSED"); lua_pushinteger(L, LV_EVENT_DEFOCUSED); lua_settable(L, -3);
lua_pushstring(L, "LEAVE"); lua_pushinteger(L, LV_EVENT_LEAVE); lua_settable(L, -3);
lua_pushstring(L, "HIT_TEST"); lua_pushinteger(L, LV_EVENT_HIT_TEST); lua_settable(L, -3);
lua_pushstring(L, "COVER_CHECK"); lua_pushinteger(L, LV_EVENT_COVER_CHECK); lua_settable(L, -3);
lua_pushstring(L, "REFR_EXT_DRAW_SIZE"); lua_pushinteger(L, LV_EVENT_REFR_EXT_DRAW_SIZE); lua_settable(L, -3);
lua_pushstring(L, "DRAW_MAIN_BEGIN"); lua_pushinteger(L, LV_EVENT_DRAW_MAIN_BEGIN); lua_settable(L, -3);
lua_pushstring(L, "DRAW_MAIN"); lua_pushinteger(L, LV_EVENT_DRAW_MAIN); lua_settable(L, -3);
lua_pushstring(L, "DRAW_MAIN_END"); lua_pushinteger(L, LV_EVENT_DRAW_MAIN_END); lua_settable(L, -3);
lua_pushstring(L, "DRAW_POST_BEGIN"); lua_pushinteger(L, LV_EVENT_DRAW_POST_BEGIN); lua_settable(L, -3);
lua_pushstring(L, "DRAW_POST"); lua_pushinteger(L, LV_EVENT_DRAW_POST); lua_settable(L, -3);
lua_pushstring(L, "DRAW_POST_END"); lua_pushinteger(L, LV_EVENT_DRAW_POST_END); lua_settable(L, -3);
lua_pushstring(L, "DRAW_PART_BEGIN"); lua_pushinteger(L, LV_EVENT_DRAW_PART_BEGIN); lua_settable(L, -3);
lua_pushstring(L, "DRAW_PART_END"); lua_pushinteger(L, LV_EVENT_DRAW_PART_END); lua_settable(L, -3);
lua_pushstring(L, "VALUE_CHANGED"); lua_pushinteger(L, LV_EVENT_VALUE_CHANGED); lua_settable(L, -3);
lua_pushstring(L, "INSERT"); lua_pushinteger(L, LV_EVENT_INSERT); lua_settable(L, -3);
lua_pushstring(L, "REFRESH"); lua_pushinteger(L, LV_EVENT_REFRESH); lua_settable(L, -3);
lua_pushstring(L, "READY"); lua_pushinteger(L, LV_EVENT_READY); lua_settable(L, -3);
lua_pushstring(L, "CANCEL"); lua_pushinteger(L, LV_EVENT_CANCEL); lua_settable(L, -3);
lua_pushstring(L, "DELETE"); lua_pushinteger(L, LV_EVENT_DELETE); lua_settable(L, -3);
lua_pushstring(L, "CHILD_CHANGED"); lua_pushinteger(L, LV_EVENT_CHILD_CHANGED); lua_settable(L, -3);
lua_pushstring(L, "CHILD_CREATED"); lua_pushinteger(L, LV_EVENT_CHILD_CREATED); lua_settable(L, -3);
lua_pushstring(L, "CHILD_DELETED"); lua_pushinteger(L, LV_EVENT_CHILD_DELETED); lua_settable(L, -3);
lua_pushstring(L, "SCREEN_UNLOAD_START"); lua_pushinteger(L, LV_EVENT_SCREEN_UNLOAD_START); lua_settable(L, -3);
lua_pushstring(L, "SCREEN_LOAD_START"); lua_pushinteger(L, LV_EVENT_SCREEN_LOAD_START); lua_settable(L, -3);
lua_pushstring(L, "SCREEN_LOADED"); lua_pushinteger(L, LV_EVENT_SCREEN_LOADED); lua_settable(L, -3);
lua_pushstring(L, "SCREEN_UNLOADED"); lua_pushinteger(L, LV_EVENT_SCREEN_UNLOADED); lua_settable(L, -3);
lua_pushstring(L, "SIZE_CHANGED"); lua_pushinteger(L, LV_EVENT_SIZE_CHANGED); lua_settable(L, -3);
lua_pushstring(L, "STYLE_CHANGED"); lua_pushinteger(L, LV_EVENT_STYLE_CHANGED); lua_settable(L, -3);
lua_pushstring(L, "LAYOUT_CHANGED"); lua_pushinteger(L, LV_EVENT_LAYOUT_CHANGED); lua_settable(L, -3);
lua_pushstring(L, "GET_SELF_SIZE"); lua_pushinteger(L, LV_EVENT_GET_SELF_SIZE); lua_settable(L, -3);
}
static void luavgl_obj_flag_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "PRESSED"); lua_pushinteger(L, LV_EVENT_PRESSED); lua_settable(L, -3);
lua_pushstring(L, "HIDDEN"); lua_pushinteger(L, LV_OBJ_FLAG_HIDDEN); lua_settable(L, -3);
lua_pushstring(L, "CLICKABLE"); lua_pushinteger(L, LV_OBJ_FLAG_CLICKABLE); lua_settable(L, -3);
lua_pushstring(L, "CLICK_FOCUSABLE"); lua_pushinteger(L, LV_OBJ_FLAG_CLICK_FOCUSABLE); lua_settable(L, -3);
lua_pushstring(L, "CHECKABLE"); lua_pushinteger(L, LV_OBJ_FLAG_CHECKABLE); lua_settable(L, -3);
lua_pushstring(L, "SCROLLABLE"); lua_pushinteger(L, LV_OBJ_FLAG_SCROLLABLE); lua_settable(L, -3);
lua_pushstring(L, "SCROLL_ELASTIC"); lua_pushinteger(L, LV_OBJ_FLAG_SCROLL_ELASTIC); lua_settable(L, -3);
lua_pushstring(L, "SCROLL_MOMENTUM"); lua_pushinteger(L, LV_OBJ_FLAG_SCROLL_MOMENTUM); lua_settable(L, -3);
lua_pushstring(L, "SCROLL_ONE"); lua_pushinteger(L, LV_OBJ_FLAG_SCROLL_ONE); lua_settable(L, -3);
lua_pushstring(L, "SCROLL_CHAIN_HOR"); lua_pushinteger(L, LV_OBJ_FLAG_SCROLL_CHAIN_HOR); lua_settable(L, -3);
lua_pushstring(L, "SCROLL_CHAIN_VER"); lua_pushinteger(L, LV_OBJ_FLAG_SCROLL_CHAIN_VER); lua_settable(L, -3);
lua_pushstring(L, "SCROLL_CHAIN"); lua_pushinteger( L, LV_OBJ_FLAG_SCROLL_CHAIN_HOR | LV_OBJ_FLAG_SCROLL_CHAIN_VER); lua_settable(L, -3);
lua_pushstring(L, "SCROLL_ON_FOCUS"); lua_pushinteger(L, LV_OBJ_FLAG_SCROLL_ON_FOCUS); lua_settable(L, -3);
lua_pushstring(L, "SCROLL_WITH_ARROW"); lua_pushinteger(L, LV_OBJ_FLAG_SCROLL_WITH_ARROW); lua_settable(L, -3);
lua_pushstring(L, "SNAPPABLE"); lua_pushinteger(L, LV_OBJ_FLAG_SNAPPABLE); lua_settable(L, -3);
lua_pushstring(L, "PRESS_LOCK"); lua_pushinteger(L, LV_OBJ_FLAG_PRESS_LOCK); lua_settable(L, -3);
lua_pushstring(L, "EVENT_BUBBLE"); lua_pushinteger(L, LV_OBJ_FLAG_EVENT_BUBBLE); lua_settable(L, -3);
lua_pushstring(L, "GESTURE_BUBBLE"); lua_pushinteger(L, LV_OBJ_FLAG_GESTURE_BUBBLE); lua_settable(L, -3);
lua_pushstring(L, "ADV_HITTEST"); lua_pushinteger(L, LV_OBJ_FLAG_ADV_HITTEST); lua_settable(L, -3);
lua_pushstring(L, "IGNORE_LAYOUT"); lua_pushinteger(L, LV_OBJ_FLAG_IGNORE_LAYOUT); lua_settable(L, -3);
lua_pushstring(L, "FLOATING"); lua_pushinteger(L, LV_OBJ_FLAG_FLOATING); lua_settable(L, -3);
lua_pushstring(L, "OVERFLOW_VISIBLE"); lua_pushinteger(L, LV_OBJ_FLAG_OVERFLOW_VISIBLE); lua_settable(L, -3);
lua_pushstring(L, "LAYOUT_1"); lua_pushinteger(L, LV_OBJ_FLAG_LAYOUT_1); lua_settable(L, -3);
lua_pushstring(L, "LAYOUT_2"); lua_pushinteger(L, LV_OBJ_FLAG_LAYOUT_2); lua_settable(L, -3);
lua_pushstring(L, "WIDGET_1"); lua_pushinteger(L, LV_OBJ_FLAG_WIDGET_1); lua_settable(L, -3);
lua_pushstring(L, "WIDGET_2"); lua_pushinteger(L, LV_OBJ_FLAG_WIDGET_2); lua_settable(L, -3);
lua_pushstring(L, "USER_1"); lua_pushinteger(L, LV_OBJ_FLAG_USER_1); lua_settable(L, -3);
lua_pushstring(L, "USER_2"); lua_pushinteger(L, LV_OBJ_FLAG_USER_2); lua_settable(L, -3);
lua_pushstring(L, "USER_3"); lua_pushinteger(L, LV_OBJ_FLAG_USER_3); lua_settable(L, -3);
lua_pushstring(L, "USER_4"); lua_pushinteger(L, LV_OBJ_FLAG_USER_4); lua_settable(L, -3);
}
static void luavgl_state_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "DEFAULT"); lua_pushinteger(L, LV_STATE_DEFAULT); lua_settable(L, -3);
lua_pushstring(L, "CHECKED"); lua_pushinteger(L, LV_STATE_CHECKED); lua_settable(L, -3);
lua_pushstring(L, "FOCUSED"); lua_pushinteger(L, LV_STATE_FOCUSED); lua_settable(L, -3);
lua_pushstring(L, "FOCUS_KEY"); lua_pushinteger(L, LV_STATE_FOCUS_KEY); lua_settable(L, -3);
lua_pushstring(L, "EDITED"); lua_pushinteger(L, LV_STATE_EDITED); lua_settable(L, -3);
lua_pushstring(L, "HOVERED"); lua_pushinteger(L, LV_STATE_HOVERED); lua_settable(L, -3);
lua_pushstring(L, "PRESSED"); lua_pushinteger(L, LV_STATE_PRESSED); lua_settable(L, -3);
lua_pushstring(L, "SCROLLED"); lua_pushinteger(L, LV_STATE_SCROLLED); lua_settable(L, -3);
lua_pushstring(L, "DISABLED"); lua_pushinteger(L, LV_STATE_DISABLED); lua_settable(L, -3);
lua_pushstring(L, "USER_1"); lua_pushinteger(L, LV_STATE_USER_1); lua_settable(L, -3);
lua_pushstring(L, "USER_2"); lua_pushinteger(L, LV_STATE_USER_2); lua_settable(L, -3);
lua_pushstring(L, "USER_3"); lua_pushinteger(L, LV_STATE_USER_3); lua_settable(L, -3);
lua_pushstring(L, "USER_4"); lua_pushinteger(L, LV_STATE_USER_4); lua_settable(L, -3);
lua_pushstring(L, "ANY"); lua_pushinteger(L, LV_STATE_ANY); lua_settable(L, -3);
}
static void luavgl_part_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "MAIN"); lua_pushinteger(L, LV_PART_MAIN); lua_settable(L, -3);
lua_pushstring(L, "SCROLLBAR"); lua_pushinteger(L, LV_PART_SCROLLBAR); lua_settable(L, -3);
lua_pushstring(L, "INDICATOR"); lua_pushinteger(L, LV_PART_INDICATOR); lua_settable(L, -3);
lua_pushstring(L, "KNOB"); lua_pushinteger(L, LV_PART_KNOB); lua_settable(L, -3);
lua_pushstring(L, "SELECTED"); lua_pushinteger(L, LV_PART_SELECTED); lua_settable(L, -3);
lua_pushstring(L, "ITEMS"); lua_pushinteger(L, LV_PART_ITEMS); lua_settable(L, -3);
lua_pushstring(L, "TICKS"); lua_pushinteger(L, LV_PART_TICKS); lua_settable(L, -3);
lua_pushstring(L, "CURSOR"); lua_pushinteger(L, LV_PART_CURSOR); lua_settable(L, -3);
lua_pushstring(L, "CUSTOM_FIRST"); lua_pushinteger(L, LV_PART_CUSTOM_FIRST); lua_settable(L, -3);
lua_pushstring(L, "ANY"); lua_pushinteger(L, LV_PART_ANY); lua_settable(L, -3);
}
static void luavgl_align_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "DEFAULT"); lua_pushinteger(L, LV_ALIGN_DEFAULT); lua_settable(L, -3);
lua_pushstring(L, "TOP_LEFT"); lua_pushinteger(L, LV_ALIGN_TOP_LEFT); lua_settable(L, -3);
lua_pushstring(L, "TOP_MID"); lua_pushinteger(L, LV_ALIGN_TOP_MID); lua_settable(L, -3);
lua_pushstring(L, "TOP_RIGHT"); lua_pushinteger(L, LV_ALIGN_TOP_RIGHT); lua_settable(L, -3);
lua_pushstring(L, "BOTTOM_LEFT"); lua_pushinteger(L, LV_ALIGN_BOTTOM_LEFT); lua_settable(L, -3);
lua_pushstring(L, "BOTTOM_MID"); lua_pushinteger(L, LV_ALIGN_BOTTOM_MID); lua_settable(L, -3);
lua_pushstring(L, "BOTTOM_RIGHT"); lua_pushinteger(L, LV_ALIGN_BOTTOM_RIGHT); lua_settable(L, -3);
lua_pushstring(L, "LEFT_MID"); lua_pushinteger(L, LV_ALIGN_LEFT_MID); lua_settable(L, -3);
lua_pushstring(L, "RIGHT_MID"); lua_pushinteger(L, LV_ALIGN_RIGHT_MID); lua_settable(L, -3);
lua_pushstring(L, "CENTER"); lua_pushinteger(L, LV_ALIGN_CENTER); lua_settable(L, -3);
lua_pushstring(L, "OUT_TOP_LEFT"); lua_pushinteger(L, LV_ALIGN_OUT_TOP_LEFT); lua_settable(L, -3);
lua_pushstring(L, "OUT_TOP_MID"); lua_pushinteger(L, LV_ALIGN_OUT_TOP_MID); lua_settable(L, -3);
lua_pushstring(L, "OUT_TOP_RIGHT"); lua_pushinteger(L, LV_ALIGN_OUT_TOP_RIGHT); lua_settable(L, -3);
lua_pushstring(L, "OUT_BOTTOM_LEFT"); lua_pushinteger(L, LV_ALIGN_OUT_BOTTOM_LEFT); lua_settable(L, -3);
lua_pushstring(L, "OUT_BOTTOM_MID"); lua_pushinteger(L, LV_ALIGN_OUT_BOTTOM_MID); lua_settable(L, -3);
lua_pushstring(L, "OUT_BOTTOM_RIGHT"); lua_pushinteger(L, LV_ALIGN_OUT_BOTTOM_RIGHT); lua_settable(L, -3);
lua_pushstring(L, "OUT_LEFT_TOP"); lua_pushinteger(L, LV_ALIGN_OUT_LEFT_TOP); lua_settable(L, -3);
lua_pushstring(L, "OUT_LEFT_MID"); lua_pushinteger(L, LV_ALIGN_OUT_LEFT_MID); lua_settable(L, -3);
lua_pushstring(L, "OUT_LEFT_BOTTOM"); lua_pushinteger(L, LV_ALIGN_OUT_LEFT_BOTTOM); lua_settable(L, -3);
lua_pushstring(L, "OUT_RIGHT_TOP"); lua_pushinteger(L, LV_ALIGN_OUT_RIGHT_TOP); lua_settable(L, -3);
lua_pushstring(L, "OUT_RIGHT_MID"); lua_pushinteger(L, LV_ALIGN_OUT_RIGHT_MID); lua_settable(L, -3);
lua_pushstring(L, "OUT_RIGHT_BOTTOM"); lua_pushinteger(L, LV_ALIGN_OUT_RIGHT_BOTTOM); lua_settable(L, -3);
}
static void luavgl_label_const_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "LONG_WRAP"); lua_pushinteger(L, LV_LABEL_LONG_WRAP); lua_settable(L, -3);
lua_pushstring(L, "LONG_DOT"); lua_pushinteger(L, LV_LABEL_LONG_DOT); lua_settable(L, -3);
lua_pushstring(L, "LONG_SCROLL"); lua_pushinteger(L, LV_LABEL_LONG_SCROLL); lua_settable(L, -3);
lua_pushstring(L, "LONG_SCROLL_CIRCULAR"); lua_pushinteger(L, LV_LABEL_LONG_SCROLL_CIRCULAR); lua_settable(L, -3);
lua_pushstring(L, "LONG_CLIP"); lua_pushinteger(L, LV_LABEL_LONG_CLIP); lua_settable(L, -3);
}
static void luavgl_builtin_font_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "DEFAULT"); lua_pushlightuserdata(L, (void*)LV_FONT_DEFAULT); lua_settable(L, -3);
#if LV_FONT_MONTSERRAT_8
LV_FONT_DECLARE(lv_font_montserrat_8)
lua_pushstring(L, "MONTSERRAT_8"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_8); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_10
LV_FONT_DECLARE(lv_font_montserrat_10)
lua_pushstring(L, "MONTSERRAT_10"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_10); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_12
LV_FONT_DECLARE(lv_font_montserrat_12)
lua_pushstring(L, "MONTSERRAT_12"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_12); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_14
LV_FONT_DECLARE(lv_font_montserrat_14)
lua_pushstring(L, "MONTSERRAT_14"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_14); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_16
LV_FONT_DECLARE(lv_font_montserrat_16)
lua_pushstring(L, "MONTSERRAT_16"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_16); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_18
LV_FONT_DECLARE(lv_font_montserrat_18)
lua_pushstring(L, "MONTSERRAT_18"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_18); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_20
LV_FONT_DECLARE(lv_font_montserrat_20)
lua_pushstring(L, "MONTSERRAT_20"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_20); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_22
LV_FONT_DECLARE(lv_font_montserrat_22)
lua_pushstring(L, "MONTSERRAT_22"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_22); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_24
LV_FONT_DECLARE(lv_font_montserrat_24)
lua_pushstring(L, "MONTSERRAT_24"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_24); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_26
LV_FONT_DECLARE(lv_font_montserrat_26)
lua_pushstring(L, "MONTSERRAT_26"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_26); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_28
LV_FONT_DECLARE(lv_font_montserrat_28)
lua_pushstring(L, "MONTSERRAT_28"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_28); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_30
LV_FONT_DECLARE(lv_font_montserrat_30)
lua_pushstring(L, "MONTSERRAT_30"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_30); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_32
LV_FONT_DECLARE(lv_font_montserrat_32)
lua_pushstring(L, "MONTSERRAT_32"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_32); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_34
LV_FONT_DECLARE(lv_font_montserrat_34)
lua_pushstring(L, "MONTSERRAT_34"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_34); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_36
LV_FONT_DECLARE(lv_font_montserrat_36)
lua_pushstring(L, "MONTSERRAT_36"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_36); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_38
LV_FONT_DECLARE(lv_font_montserrat_38)
lua_pushstring(L, "MONTSERRAT_38"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_38); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_40
LV_FONT_DECLARE(lv_font_montserrat_40)
lua_pushstring(L, "MONTSERRAT_40"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_40); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_42
LV_FONT_DECLARE(lv_font_montserrat_42)
lua_pushstring(L, "MONTSERRAT_42"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_42); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_44
LV_FONT_DECLARE(lv_font_montserrat_44)
lua_pushstring(L, "MONTSERRAT_44"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_44); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_46
LV_FONT_DECLARE(lv_font_montserrat_46)
lua_pushstring(L, "MONTSERRAT_46"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_46); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_48
LV_FONT_DECLARE(lv_font_montserrat_48)
lua_pushstring(L, "MONTSERRAT_48"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_48); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_12_SUBPX
LV_FONT_DECLARE(lv_font_montserrat_12_subpx)
lua_pushstring(L, "MONTSERRAT_12_SUBPX"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_12_subpx); lua_settable(L, -3);
#endif
#if LV_FONT_MONTSERRAT_28_COMPRESSED
LV_FONT_DECLARE(lv_font_montserrat_28_compressed)
lua_pushstring(L, "MONTSERRAT_28_COMPRESSED"); lua_pushlightuserdata(L, (void*)&lv_font_montserrat_28_compressed); lua_settable(L, -3);
#endif
#if LV_FONT_DEJAVU_16_PERSIAN_HEBREW
LV_FONT_DECLARE(lv_font_dejavu_16_persian_hebrew)
lua_pushstring(L, "DEJAVU_16_PERSIAN_HEBREW"); lua_pushlightuserdata(L, (void*)&lv_font_dejavu_16_persian_hebrew); lua_settable(L, -3);
#endif
#if LV_FONT_SIMSUN_16_CJK
LV_FONT_DECLARE(lv_font_simsun_16_cjk)
lua_pushstring(L, "SIMSUN_16_CJK"); lua_pushlightuserdata(L, (void*)&lv_font_simsun_16_cjk); lua_settable(L, -3);
#endif
#if LV_FONT_UNSCII_8
LV_FONT_DECLARE(lv_font_unscii_8)
lua_pushstring(L, "UNSCII_8"); lua_pushlightuserdata(L, (void*)&lv_font_unscii_8); lua_settable(L, -3);
#endif
#if LV_FONT_UNSCII_16
LV_FONT_DECLARE(lv_font_unscii_16)
lua_pushstring(L, "UNSCII_16"); lua_pushlightuserdata(L, (void*)&lv_font_unscii_16); lua_settable(L, -3);
#endif
}
static void luavgl_scr_load_anim_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "NONE"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_NONE); lua_settable(L, -3);
lua_pushstring(L, "OVER_LEFT"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_OVER_LEFT); lua_settable(L, -3);
lua_pushstring(L, "OVER_RIGHT"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_OVER_RIGHT); lua_settable(L, -3);
lua_pushstring(L, "OVER_TOP"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_OVER_TOP); lua_settable(L, -3);
lua_pushstring(L, "OVER_BOTTOM"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_OVER_BOTTOM); lua_settable(L, -3);
lua_pushstring(L, "MOVE_LEFT"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_MOVE_LEFT); lua_settable(L, -3);
lua_pushstring(L, "MOVE_RIGHT"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_MOVE_RIGHT); lua_settable(L, -3);
lua_pushstring(L, "MOVE_TOP"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_MOVE_TOP); lua_settable(L, -3);
lua_pushstring(L, "MOVE_BOTTOM"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_MOVE_BOTTOM); lua_settable(L, -3);
lua_pushstring(L, "FADE_IN"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_FADE_IN); lua_settable(L, -3);
lua_pushstring(L, "FADE_ON"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_FADE_ON); lua_settable(L, -3);
lua_pushstring(L, "FADE_OUT"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_FADE_OUT); lua_settable(L, -3);
lua_pushstring(L, "OUT_LEFT"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_OUT_LEFT); lua_settable(L, -3);
lua_pushstring(L, "OUT_RIGHT"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_OUT_RIGHT); lua_settable(L, -3);
lua_pushstring(L, "OUT_TOP"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_OUT_TOP); lua_settable(L, -3);
lua_pushstring(L, "OUT_BOTTOM"); lua_pushinteger(L, LV_SCR_LOAD_ANIM_OUT_BOTTOM); lua_settable(L, -3);
}
static void luavgl_scrollbar_mode_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "OFF"); lua_pushinteger(L, LV_SCROLLBAR_MODE_OFF); lua_settable(L, -3);
lua_pushstring(L, "ON"); lua_pushinteger(L, LV_SCROLLBAR_MODE_ON); lua_settable(L, -3);
lua_pushstring(L, "ACTIVE"); lua_pushinteger(L, LV_SCROLLBAR_MODE_ACTIVE); lua_settable(L, -3);
lua_pushstring(L, "AUTO"); lua_pushinteger(L, LV_SCROLLBAR_MODE_AUTO); lua_settable(L, -3);
}
static void luavgl_dir_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "NONE"); lua_pushinteger(L, LV_DIR_NONE); lua_settable(L, -3);
lua_pushstring(L, "LEFT"); lua_pushinteger(L, LV_DIR_LEFT); lua_settable(L, -3);
lua_pushstring(L, "RIGHT"); lua_pushinteger(L, LV_DIR_RIGHT); lua_settable(L, -3);
lua_pushstring(L, "TOP"); lua_pushinteger(L, LV_DIR_TOP); lua_settable(L, -3);
lua_pushstring(L, "BOTTOM"); lua_pushinteger(L, LV_DIR_BOTTOM); lua_settable(L, -3);
lua_pushstring(L, "HOR"); lua_pushinteger(L, LV_DIR_HOR); lua_settable(L, -3);
lua_pushstring(L, "VER"); lua_pushinteger(L, LV_DIR_VER); lua_settable(L, -3);
lua_pushstring(L, "ALL"); lua_pushinteger(L, LV_DIR_ALL); lua_settable(L, -3);
}
static void luavgl_keyboard_mode_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "TEXT_LOWER"); lua_pushinteger(L, LV_KEYBOARD_MODE_TEXT_LOWER); lua_settable(L, -3);
lua_pushstring(L, "TEXT_UPPER"); lua_pushinteger(L, LV_KEYBOARD_MODE_TEXT_UPPER); lua_settable(L, -3);
lua_pushstring(L, "SPECIAL"); lua_pushinteger(L, LV_KEYBOARD_MODE_SPECIAL); lua_settable(L, -3);
lua_pushstring(L, "NUMBER"); lua_pushinteger(L, LV_KEYBOARD_MODE_NUMBER); lua_settable(L, -3);
lua_pushstring(L, "USER_1"); lua_pushinteger(L, LV_KEYBOARD_MODE_USER_1); lua_settable(L, -3);
lua_pushstring(L, "USER_2"); lua_pushinteger(L, LV_KEYBOARD_MODE_USER_2); lua_settable(L, -3);
lua_pushstring(L, "USER_3"); lua_pushinteger(L, LV_KEYBOARD_MODE_USER_3); lua_settable(L, -3);
lua_pushstring(L, "USER_4"); lua_pushinteger(L, LV_KEYBOARD_MODE_USER_4); lua_settable(L, -3);
#if LV_USE_ARABIC_PERSIAN_CHARS == 1
lua_pushstring(L, "TEXT_ARABIC"); lua_pushinteger(L, LV_KEYBOARD_MODE_TEXT_ARABIC); lua_settable(L, -3);
#endif
}
static void luavgl_flex_flow_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "ROW"); lua_pushinteger(L, LV_FLEX_FLOW_ROW); lua_settable(L, -3);
lua_pushstring(L, "COLUMN"); lua_pushinteger(L, LV_FLEX_FLOW_COLUMN); lua_settable(L, -3);
lua_pushstring(L, "ROW_WRAP"); lua_pushinteger(L, LV_FLEX_FLOW_ROW_WRAP); lua_settable(L, -3);
lua_pushstring(L, "ROW_REVERSE"); lua_pushinteger(L, LV_FLEX_FLOW_ROW_REVERSE); lua_settable(L, -3);
lua_pushstring(L, "ROW_WRAP_REVERSE"); lua_pushinteger(L, LV_FLEX_FLOW_ROW_WRAP_REVERSE); lua_settable(L, -3);
lua_pushstring(L, "COLUMN_WRAP"); lua_pushinteger(L, LV_FLEX_FLOW_COLUMN_WRAP); lua_settable(L, -3);
lua_pushstring(L, "COLUMN_REVERSE"); lua_pushinteger(L, LV_FLEX_FLOW_COLUMN_REVERSE); lua_settable(L, -3);
lua_pushstring(L, "COLUMN_WRAP_REVERSE"); lua_pushinteger(L, LV_FLEX_FLOW_COLUMN_WRAP_REVERSE); lua_settable(L, -3);
}
static void luavgl_flex_align_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "START"); lua_pushinteger(L, LV_FLEX_ALIGN_START); lua_settable(L, -3);
lua_pushstring(L, "END"); lua_pushinteger(L, LV_FLEX_ALIGN_END); lua_settable(L, -3);
lua_pushstring(L, "CENTER"); lua_pushinteger(L, LV_FLEX_ALIGN_CENTER); lua_settable(L, -3);
lua_pushstring(L, "SPACE_EVENLY"); lua_pushinteger(L, LV_FLEX_ALIGN_SPACE_EVENLY); lua_settable(L, -3);
lua_pushstring(L, "SPACE_AROUND"); lua_pushinteger(L, LV_FLEX_ALIGN_SPACE_AROUND); lua_settable(L, -3);
lua_pushstring(L, "SPACE_BETWEEN"); lua_pushinteger(L, LV_FLEX_ALIGN_SPACE_BETWEEN); lua_settable(L, -3);
}
static void luavgl_grid_align_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "START"); lua_pushinteger(L, LV_GRID_ALIGN_START); lua_settable(L, -3);
lua_pushstring(L, "CENTER"); lua_pushinteger(L, LV_GRID_ALIGN_CENTER); lua_settable(L, -3);
lua_pushstring(L, "END"); lua_pushinteger(L, LV_GRID_ALIGN_END); lua_settable(L, -3);
lua_pushstring(L, "STRETCH"); lua_pushinteger(L, LV_GRID_ALIGN_STRETCH); lua_settable(L, -3);
lua_pushstring(L, "SPACE_EVENLY"); lua_pushinteger(L, LV_GRID_ALIGN_SPACE_EVENLY); lua_settable(L, -3);
lua_pushstring(L, "SPACE_AROUND"); lua_pushinteger(L, LV_GRID_ALIGN_SPACE_AROUND); lua_settable(L, -3);
lua_pushstring(L, "SPACE_BETWEEN"); lua_pushinteger(L, LV_GRID_ALIGN_SPACE_BETWEEN); lua_settable(L, -3);
}
static void luavgl_roller_mode_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "NORMAL"); lua_pushinteger(L, LV_ROLLER_MODE_NORMAL); lua_settable(L, -3);
lua_pushstring(L, "INFINITE"); lua_pushinteger(L, LV_ROLLER_MODE_INFINITE); lua_settable(L, -3);
}
static void luavgl_key_init(lua_State* L)
{
lua_newtable(L);
lua_pushstring(L, "UP"); lua_pushinteger(L, LV_KEY_UP); lua_settable(L, -3);
lua_pushstring(L, "DOWN"); lua_pushinteger(L, LV_KEY_DOWN); lua_settable(L, -3);
lua_pushstring(L, "RIGHT"); lua_pushinteger(L, LV_KEY_RIGHT); lua_settable(L, -3);
lua_pushstring(L, "LEFT"); lua_pushinteger(L, LV_KEY_LEFT); lua_settable(L, -3);
lua_pushstring(L, "ESC"); lua_pushinteger(L, LV_KEY_ESC); lua_settable(L, -3);
lua_pushstring(L, "DEL"); lua_pushinteger(L, LV_KEY_DEL); lua_settable(L, -3);
lua_pushstring(L, "BACKSPACE"); lua_pushinteger(L, LV_KEY_BACKSPACE); lua_settable(L, -3);
lua_pushstring(L, "ENTER"); lua_pushinteger(L, LV_KEY_ENTER); lua_settable(L, -3);
lua_pushstring(L, "NEXT"); lua_pushinteger(L, LV_KEY_NEXT); lua_settable(L, -3);
lua_pushstring(L, "PREV"); lua_pushinteger(L, LV_KEY_PREV); lua_settable(L, -3);
lua_pushstring(L, "HOME"); lua_pushinteger(L, LV_KEY_HOME); lua_settable(L, -3);
lua_pushstring(L, "END"); lua_pushinteger(L, LV_KEY_END); lua_settable(L, -3);
}
static int luavgl_LV_PCT(lua_State*L)
{
int pct = lua_tointeger(L, 1);
lua_pushinteger(L, LV_PCT(pct));
return 1;
}
static int luavgl_LV_OPA(lua_State*L)
{
int opa = luavgl_tointeger(L, 1) * LV_OPA_100 / 100;
if (opa > 255)
opa = 255;
if (opa < 0)
opa = 0;
lua_pushinteger(L, opa);
return 1;
}
static int luavgl_LV_HOR_RES(lua_State*L)
{
lua_pushinteger(L, LV_HOR_RES);
return 1;
}
static int luavgl_LV_VER_RES(lua_State*L)
{
lua_pushinteger(L, LV_VER_RES);
return 1;
}
/* clang-format on */
static void luavgl_constants_init(lua_State *L)
{
luavgl_event_code_init(L);
lua_setfield(L, -2, "EVENT");
luavgl_obj_flag_init(L);
lua_setfield(L, -2, "FLAG");
luavgl_state_init(L);
lua_setfield(L, -2, "STATE");
luavgl_part_init(L);
lua_setfield(L, -2, "PART");
luavgl_align_init(L);
lua_setfield(L, -2, "ALIGN");
luavgl_builtin_font_init(L);
lua_setfield(L, -2, "BUILTIN_FONT");
luavgl_label_const_init(L);
lua_setfield(L, -2, "LABEL");
luavgl_scr_load_anim_init(L);
lua_setfield(L, -2, "SCR_LOAD_ANIM");
luavgl_scrollbar_mode_init(L);
lua_setfield(L, -2, "SCROLLBAR_MODE");
luavgl_dir_init(L);
lua_setfield(L, -2, "DIR");
luavgl_keyboard_mode_init(L);
lua_setfield(L, -2, "KEYBOARD_MODE");
luavgl_flex_flow_init(L);
lua_setfield(L, -2, "FLEX_FLOW");
luavgl_flex_align_init(L);
lua_setfield(L, -2, "FLEX_ALIGN");
luavgl_grid_align_init(L);
lua_setfield(L, -2, "GRID_ALIGN");
luavgl_roller_mode_init(L);
lua_setfield(L, -2, "ROLLER_MODE");
luavgl_key_init(L);
lua_setfield(L, -2, "KEY");
/* miscellaneous. */
lua_pushinteger(L, LV_ANIM_REPEAT_INFINITE);
lua_setfield(L, -2, "ANIM_REPEAT_INFINITE");
lua_pushinteger(L, LV_ANIM_PLAYTIME_INFINITE);
lua_setfield(L, -2, "ANIM_PLAYTIME_INFINITE");
lua_pushcfunction(L, luavgl_LV_OPA);
lua_setfield(L, -2, "OPA");
lua_pushcfunction(L, luavgl_LV_PCT);
lua_setfield(L, -2, "PCT");
lua_pushinteger(L, LV_SIZE_CONTENT);
lua_setfield(L, -2, "SIZE_CONTENT");
lua_pushinteger(L, LV_RADIUS_CIRCLE);
lua_setfield(L, -2, "RADIUS_CIRCLE");
lua_pushinteger(L, LV_COORD_MAX);
lua_setfield(L, -2, "COORD_MAX");
lua_pushinteger(L, LV_COORD_MIN);
lua_setfield(L, -2, "COORD_MIN");
lua_pushinteger(L, LV_IMG_ZOOM_NONE);
lua_setfield(L, -2, "IMG_ZOOM_NONE");
lua_pushinteger(L, LV_BTNMATRIX_BTN_NONE);
lua_setfield(L, -2, "BTNMATRIX_BTN_NONE");
lua_pushinteger(L, LV_CHART_POINT_NONE);
lua_setfield(L, -2, "CHART_POINT_NONE");
lua_pushinteger(L, LV_DROPDOWN_POS_LAST);
lua_setfield(L, -2, "DROPDOWN_POS_LAST");
lua_pushinteger(L, LV_LABEL_DOT_NUM);
lua_setfield(L, -2, "LABEL_DOT_NUM");
lua_pushinteger(L, LV_LABEL_POS_LAST);
lua_setfield(L, -2, "LABEL_POS_LAST");
lua_pushinteger(L, LV_LABEL_TEXT_SELECTION_OFF);
lua_setfield(L, -2, "LABEL_TEXT_SELECTION_OFF");
lua_pushinteger(L, LV_TABLE_CELL_NONE);
lua_setfield(L, -2, "TABLE_CELL_NONE");
lua_pushinteger(L, LV_TEXTAREA_CURSOR_LAST);
lua_setfield(L, -2, "TEXTAREA_CURSOR_LAST");
lua_pushinteger(L, LV_LAYOUT_FLEX);
lua_setfield(L, -2, "LAYOUT_FLEX");
lua_pushinteger(L, LV_LAYOUT_GRID);
lua_setfield(L, -2, "LAYOUT_GRID");
lua_pushcfunction(L, luavgl_LV_HOR_RES);
lua_setfield(L, -2, "HOR_RES");
lua_pushcfunction(L, luavgl_LV_VER_RES);
lua_setfield(L, -2, "VER_RES");
}
+342
View File
@@ -0,0 +1,342 @@
#include "luavgl.h"
#include "private.h"
typedef struct luavgl_disp_s {
lv_disp_t *disp;
} luavgl_disp_t;
static luavgl_disp_t *luavgl_check_disp(lua_State *L, int idx)
{
luavgl_disp_t *v = luaL_checkudata(L, idx, "lv_disp");
return v;
}
static lv_disp_t *luavgl_to_disp(lua_State *L, int idx)
{
return luavgl_check_disp(L, idx)->disp;
}
static int luavgl_disp_get(lua_State *L, lv_disp_t *disp)
{
/* check if already exists */
lua_pushlightuserdata(L, disp);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
/* create new disp userdata and add to registry forever */
lua_pop(L, 1);
luavgl_disp_t *d = lua_newuserdata(L, sizeof(luavgl_disp_t));
d->disp = disp;
luaL_getmetatable(L, "lv_disp");
lua_setmetatable(L, -2);
lua_pushlightuserdata(L, disp);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX);
}
return 1;
}
static int luavgl_disp_get_default(lua_State *L)
{
lv_disp_t *disp = lv_disp_get_default();
return luavgl_disp_get(L, disp);
}
static int luavgl_disp_get_scr_act(lua_State *L)
{
lv_disp_t *disp = luavgl_to_disp(L, 1);
lv_obj_t *obj = lv_disp_get_scr_act(disp);
if (obj == NULL) {
lua_pushnil(L);
return 1;
}
/* registry[obj] */
lua_pushlightuserdata(L, obj);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
luavgl_add_lobj(L, obj)->lua_created = false;
}
return 1;
}
static int luavgl_disp_get_scr_prev(lua_State *L)
{
luavgl_disp_t *d = luavgl_check_disp(L, 1);
lv_obj_t *obj = lv_disp_get_scr_prev(d->disp);
if (obj == NULL) {
lua_pushnil(L);
return 1;
}
/* registry[obj] */
lua_pushlightuserdata(L, obj);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
luavgl_add_lobj(L, obj)->lua_created = false;
}
return 1;
}
/**
* luavgl.disp.load_scr(obj, {
* anim = "over_left",
* time = 1000,
* delay = 100,
* })
*/
static int luavgl_disp_load_scr(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, 2)) {
lv_disp_load_scr(obj);
return 0;
}
/* has parameter table */
lv_scr_load_anim_t anim = LV_SCR_LOAD_ANIM_NONE;
uint32_t time = 0;
uint32_t delay = 0;
bool auto_del = false;
const char *str;
lua_getfield(L, 2, "anim");
str = lua_tostring(L, -1);
if (str == NULL || strcmp(str, "none") == 0) {
; /* use default */
} else if (strcmp(str, "over_left") == 0) {
anim = LV_SCR_LOAD_ANIM_OVER_LEFT;
} else if (strcmp(str, "over_right") == 0) {
anim = LV_SCR_LOAD_ANIM_OVER_RIGHT;
} else if (strcmp(str, "over_top") == 0) {
anim = LV_SCR_LOAD_ANIM_OVER_TOP;
} else if (strcmp(str, "over_botto") == 0) {
anim = LV_SCR_LOAD_ANIM_OVER_BOTTOM;
} else if (strcmp(str, "move_left") == 0) {
anim = LV_SCR_LOAD_ANIM_MOVE_LEFT;
} else if (strcmp(str, "move_right") == 0) {
anim = LV_SCR_LOAD_ANIM_MOVE_RIGHT;
} else if (strcmp(str, "move_top") == 0) {
anim = LV_SCR_LOAD_ANIM_MOVE_TOP;
} else if (strcmp(str, "move_botto") == 0) {
anim = LV_SCR_LOAD_ANIM_MOVE_BOTTOM;
} else if (strcmp(str, "fade_in") == 0) {
anim = LV_SCR_LOAD_ANIM_FADE_IN;
} else if (strcmp(str, "fade_on") == 0) {
anim = LV_SCR_LOAD_ANIM_FADE_ON;
} else if (strcmp(str, "fade_out") == 0) {
anim = LV_SCR_LOAD_ANIM_FADE_OUT;
} else if (strcmp(str, "out_left") == 0) {
anim = LV_SCR_LOAD_ANIM_OUT_LEFT;
} else if (strcmp(str, "out_right") == 0) {
anim = LV_SCR_LOAD_ANIM_OUT_RIGHT;
} else if (strcmp(str, "out_top") == 0) {
anim = LV_SCR_LOAD_ANIM_OUT_TOP;
} else if (strcmp(str, "out_bottom") == 0) {
anim = LV_SCR_LOAD_ANIM_OUT_BOTTOM;
}
lua_pop(L, 1);
lua_getfield(L, 2, "time");
time = luavgl_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, 2, "delay");
delay = luavgl_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, 2, "auto_del");
auto_del = luavgl_tointeger(L, -1);
lua_pop(L, 1);
lv_scr_load_anim(obj, anim, time, delay, auto_del);
return 0;
}
static int luavgl_disp_get_layer_top(lua_State *L)
{
luavgl_disp_t *d = luavgl_check_disp(L, 1);
lv_obj_t *obj = lv_disp_get_layer_top(d->disp);
if (obj == NULL) {
lua_pushnil(L);
return 1;
}
/* registry[obj] */
lua_pushlightuserdata(L, obj);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
luavgl_add_lobj(L, obj)->lua_created = false;
}
return 1;
}
static int luavgl_disp_get_layer_sys(lua_State *L)
{
luavgl_disp_t *d = luavgl_check_disp(L, 1);
lv_obj_t *obj = lv_disp_get_layer_sys(d->disp);
if (obj == NULL) {
lua_pushnil(L);
return 1;
}
/* registry[obj] */
lua_pushlightuserdata(L, obj);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
luavgl_add_lobj(L, obj)->lua_created = false;
}
return 1;
}
static int luavgl_disp_set_bg_color(lua_State *L)
{
luavgl_disp_t *d = luavgl_check_disp(L, 1);
lv_color_t c = luavgl_tocolor(L, 2);
lv_disp_set_bg_color(d->disp, c);
return 0;
}
static int luavgl_disp_set_bg_image(lua_State *L)
{
luavgl_disp_t *d = luavgl_check_disp(L, 1);
const char *img = luavgl_toimgsrc(L, 2);
lv_disp_set_bg_image(d->disp, img);
return 0;
}
static int luavgl_disp_set_bg_opa(lua_State *L)
{
luavgl_disp_t *d = luavgl_check_disp(L, 1);
lv_opa_t opa = luavgl_tointeger(L, 2);
lv_disp_set_bg_opa(d->disp, opa);
return 0;
}
static int luavgl_disp_get_chroma_key_color(lua_State *L)
{
#if LVGL_VERSION_MAJOR >= 9
luavgl_disp_t *d = luavgl_check_disp(L, 1);
lv_color_t c = lv_disp_get_chroma_key_color(d->disp);
lua_pushinteger(L, c.full);
#else
lua_pushinteger(L, 0);
#endif
return 1;
}
static int luavgl_disp_get_next(lua_State *L)
{
lv_disp_t *disp = NULL;
if (!lua_isnoneornil(L, 1)) {
disp = luavgl_check_disp(L, 1)->disp;
}
disp = lv_disp_get_next(disp);
if (disp == NULL) {
lua_pushnil(L);
return 1;
}
return luavgl_disp_get(L, disp);
}
static int luavgl_disp_get_res(lua_State *L)
{
luavgl_disp_t *d = luavgl_check_disp(L, 1);
lua_pushinteger(L, lv_disp_get_hor_res(d->disp));
lua_pushinteger(L, lv_disp_get_ver_res(d->disp));
return 2;
}
static int luavgl_disp_set_rotation(lua_State *L)
{
luavgl_disp_t *d = luavgl_check_disp(L, 1);
uint32_t r = lua_tointeger(L, 2);
lv_disp_rot_t rot;
if (r == 0)
rot = LV_DISP_ROT_NONE;
else if (r == 90)
rot = LV_DISP_ROT_90;
else if (r == 180)
rot = LV_DISP_ROT_180;
else if (r == 270)
rot = LV_DISP_ROT_270;
else {
return luaL_argerror(L, 2, "invalid rotation value");
}
lv_disp_set_rotation(d->disp, rot);
return 0;
}
/**
* luavgl.disp lib
*/
static const luaL_Reg disp_lib[] = {
{"get_default", luavgl_disp_get_default },
{"get_scr_act", luavgl_disp_get_scr_act },
{"get_scr_prev", luavgl_disp_get_scr_prev},
{"get_next", luavgl_disp_get_next },
{"load_scr", luavgl_disp_load_scr },
{NULL, NULL },
};
/*
** methods for disp handles
*/
static const luaL_Reg disp_methods[] = {
{"get_layer_top", luavgl_disp_get_layer_top },
{"get_layer_sys", luavgl_disp_get_layer_sys },
{"set_bg_color", luavgl_disp_set_bg_color },
{"set_bg_image", luavgl_disp_set_bg_image },
{"set_bg_opa", luavgl_disp_set_bg_opa },
{"get_chroma_key_color", luavgl_disp_get_chroma_key_color},
{"get_next", luavgl_disp_get_next },
{"set_rotation", luavgl_disp_set_rotation },
{"get_res", luavgl_disp_get_res },
{NULL, NULL },
};
static const luaL_Reg disp_meta[] = {
{"__index", NULL}, /* place holder */
{NULL, NULL}
};
static void luavgl_disp_init(lua_State *L)
{
/* create lv_fs metatable */
luaL_newmetatable(L, "lv_disp");
luaL_setfuncs(L, disp_meta, 0);
luaL_newlib(L, disp_methods);
lua_setfield(L, -2, "__index");
lua_pop(L, 1); /* pop metatable */
/* luavgl.disp lib */
luaL_newlib(L, disp_lib);
lua_setfield(L, -2, "disp");
}
+191
View File
@@ -0,0 +1,191 @@
#include "luavgl.h"
#include "private.h"
static void luavgl_obj_event_cb(lv_event_t *e)
{
lua_State *L = e->user_data;
if (L == NULL) {
debug("Null user data, should be L.\n");
}
int top = lua_gettop(L);
lv_obj_t *obj = e->current_target;
lua_pushlightuserdata(L, obj);
lua_rawget(L, LUA_REGISTRYINDEX);
luavgl_obj_t *lobj = luavgl_to_lobj(L, -1);
if (lobj == NULL || lobj->obj == NULL)
goto event_exit;
int ref = LUA_NOREF;
for (int i = 0; i < lobj->n_events; i++) {
if (lobj->events[i].code == LV_EVENT_ALL ||
lobj->events[i].code == e->code) {
ref = lobj->events[i].ref;
break;
}
}
if (ref == LUA_NOREF) {
/* nobody cares this event, something went wrong but can be ignored. */
goto event_exit;
}
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
lua_pushlightuserdata(L, obj);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushinteger(L, e->code);
/* args: obj, code */
luavgl_pcall_int(L, 2, 0);
event_exit:
lua_settop(L, top);
}
static void luavgl_obj_remove_event(lua_State *L, lv_obj_t *obj,
struct event_callback_s *event)
{
luaL_unref(L, LUA_REGISTRYINDEX, event->ref);
event->code = -1; /* mark it as unused. */
event->ref = LUA_NOREF;
lv_obj_remove_event_dsc(obj, event->dsc);
event->dsc = NULL;
}
/* obj:onevent(luavgl.EVENT.PRESSED, function(code, value) -- end) */
static int luavgl_obj_on_event(lua_State *L)
{
bool remove_all; /* if third parameter is noneornil, remove all events. */
luavgl_obj_t *lobj = luavgl_to_lobj(L, 1);
lv_obj_t *obj = lobj->obj;
if (obj == NULL) {
luaL_argerror(L, 1, "expect obj userdata.\n");
return 0;
}
lv_event_code_t code = lua_tointeger(L, 2);
if (code >= _LV_EVENT_LAST) {
luaL_argerror(L, 2, "event code illegal");
return 0;
}
remove_all = lua_isnoneornil(L, 3);
/* check if event code already added, find a slot to store this callback */
int slot = 0;
if (lobj && lobj->events) {
for (; slot < lobj->n_events; slot++) {
struct event_callback_s *event = &lobj->events[slot];
if (event->code == code) { /* same event can only be added once. */
luavgl_obj_remove_event(L, obj, event);
if (remove_all)
continue; /* continue to remove all events associated. */
else
break; /* use this slot for our new event callback */
}
if (event->code == -1) {
/* this callback has been removed, thus, we can use this slot */
break;
}
}
}
if (remove_all) /* no need to add, just return */
return 0;
struct event_callback_s *events = lobj->events;
/* create obj->lobj->events, if NULL, realloc if existing and find no slot
*/
if (events == NULL) {
events = calloc(sizeof(struct event_callback_s), 1);
if (events == NULL) {
return luaL_error(L, "No memory.");
}
lobj->events = events;
lobj->n_events = 1;
} else {
/* realloc? */
if (slot && slot == lobj->n_events) {
struct event_callback_s *_events;
_events = realloc(lobj->events, (lobj->n_events + 1) * sizeof(*_events));
if (_events == NULL) {
return luaL_error(L, "No memory.");
}
events = _events;
lobj->n_events++; /* now we have +1 event */
lobj->events = events;
}
/* else: we have found a slot to reuse, use it. */
}
/* setup event callback */
void *dsc = lv_obj_add_event_cb(obj, luavgl_obj_event_cb, code, L);
struct event_callback_s *event = &events[slot];
event->code = code;
event->ref = luavgl_check_continuation(L, 3);
event->dsc = dsc;
return 0;
}
/* obj:onClicked(function(code, value) end) */
static int luavgl_obj_on_clicked(lua_State *L)
{
/* stack: obj, function cb */
lua_pushinteger(L, LV_EVENT_CLICKED);
lua_insert(L, 2);
return luavgl_obj_on_event(L);
}
/* obj:onShortClicked(function(code, value) end) */
static int luavgl_obj_on_short_clicked(lua_State *L)
{
/* stack: obj, function cb */
lua_pushinteger(L, LV_EVENT_SHORT_CLICKED);
lua_insert(L, 2);
return luavgl_obj_on_event(L);
}
/* obj:onPressed(function(code, value) end) */
static int luavgl_obj_on_pressed(lua_State *L)
{
lua_pushinteger(L, LV_EVENT_PRESSED);
lua_insert(L, 2);
return luavgl_obj_on_event(L);
}
static void luavgl_obj_event_init(luavgl_obj_t *lobj) { lobj->n_events = 0; }
/**
* Remove all events added, and free memory of events
*/
static void luavgl_obj_remove_event_all(lua_State *L, luavgl_obj_t *lobj)
{
if (lobj == NULL || lobj->events == NULL) {
return;
}
struct event_callback_s *events = lobj->events;
int i = 0;
for (; i < lobj->n_events; i++) {
struct event_callback_s *event = &lobj->events[i];
if (event->code != -1) {
luavgl_obj_remove_event(L, lobj->obj, event);
}
}
free(events);
lobj->n_events = 0;
lobj->events = NULL;
}
+313
View File
@@ -0,0 +1,313 @@
#include "luavgl.h"
#include "private.h"
#define FONT_DEFAULT_SIZE 12
#define _ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
/**
* Follow css style, specify the name by name family, name size,
* name weight. Font weight can be numeric value or 'bold'. Alls strings
* are converted to lower-case before matching with local supported name.
*
* weight named weight
* 100 thin
* 200 extra light
* 300 light
* 400 normal (*default)
* 500 medium
* 600 semi bold
* 700 bold
* 800 extra bold
* 900 ultra bold
*
* Only normal weight is supported to builtin name.
*
* Font returned to lua is a userdata, it's used by object style, or style
* directly. If name is no longer ref'ed by any object or style, it's
* gc'ed.
*/
/**
* lvgl.Font("montserrat, unscii", 8, bold)
* lvgl.Font("montserrat", 8)
* lvgl.Font("montserrat")
*
* return nil if failed
*/
typedef enum {
FONT_WEIGHT_THIN = 100,
FONT_WEIGHT_EXTRA_LIGHT = 200,
FONT_WEIGHT_LIGHT = 300,
FONT_WEIGHT_NORMAL = 400,
FONT_WEIGHT_MEDIUM = 500,
FONT_WEIGHT_SEMI_BOLD = 600,
FONT_WEIGHT_BOLD = 700,
FONT_WEIGHT_EXTRA_BOLD = 800,
FONT_WEIGHT_ULTRA_BOLD = 900,
} font_weight_t;
static const struct {
char *name;
int value;
} g_named_weight[] = {
{"thin", 100},
{"extra light", 200},
{"light", 300},
{"normal", 400},
{"medium", 500},
{"semi bold", 600},
{"bold", 700},
{"extra bold", 800},
{"ultra bold", 900},
};
static const struct {
int size;
const lv_font_t *font;
} g_builtin_montserrat[] = {
#if LV_FONT_MONTSERRAT_8
{8, &lv_font_montserrat_8 },
#endif
#if LV_FONT_MONTSERRAT_10
{10, &lv_font_montserrat_10},
#endif
#if LV_FONT_MONTSERRAT_12
{12, &lv_font_montserrat_12},
#endif
#if LV_FONT_MONTSERRAT_14
{14, &lv_font_montserrat_14},
#endif
#if LV_FONT_MONTSERRAT_16
{16, &lv_font_montserrat_16},
#endif
#if LV_FONT_MONTSERRAT_18
{18, &lv_font_montserrat_18},
#endif
#if LV_FONT_MONTSERRAT_20
{20, &lv_font_montserrat_20},
#endif
#if LV_FONT_MONTSERRAT_22
{22, &lv_font_montserrat_22},
#endif
#if LV_FONT_MONTSERRAT_24
{24, &lv_font_montserrat_24},
#endif
#if LV_FONT_MONTSERRAT_26
{26, &lv_font_montserrat_26},
#endif
#if LV_FONT_MONTSERRAT_28
{28, &lv_font_montserrat_28},
#endif
#if LV_FONT_MONTSERRAT_30
{30, &lv_font_montserrat_30},
#endif
#if LV_FONT_MONTSERRAT_32
{32, &lv_font_montserrat_32},
#endif
#if LV_FONT_MONTSERRAT_34
{34, &lv_font_montserrat_34},
#endif
#if LV_FONT_MONTSERRAT_36
{36, &lv_font_montserrat_36},
#endif
#if LV_FONT_MONTSERRAT_38
{38, &lv_font_montserrat_38},
#endif
#if LV_FONT_MONTSERRAT_40
{40, &lv_font_montserrat_40},
#endif
#if LV_FONT_MONTSERRAT_42
{42, &lv_font_montserrat_42},
#endif
#if LV_FONT_MONTSERRAT_44
{44, &lv_font_montserrat_44},
#endif
#if LV_FONT_MONTSERRAT_46
{46, &lv_font_montserrat_46},
#endif
#if LV_FONT_MONTSERRAT_48
{48, &lv_font_montserrat_48},
#endif
};
static int luavgl_get_named_weight(const char *name)
{
if (name == NULL) {
return FONT_DEFAULT_SIZE;
}
for (int i = 0; i < _ARRAY_LEN(g_named_weight); i++) {
if (strcmp(name, g_named_weight[i].name) == 0) {
return g_named_weight[i].value;
}
}
return FONT_DEFAULT_SIZE;
}
static char *to_lower(char *str)
{
for (char *s = str; *s; ++s)
*s = *s >= 'A' && *s <= 'Z' ? *s | 0x60 : *s;
return str;
}
static const lv_font_t *_luavgl_font_create(lua_State *L, const char *name,
int size, int weight)
{
/* check builtin font firstly. */
if (strcmp(name, "montserrat") == 0) {
if (FONT_WEIGHT_NORMAL != weight)
return NULL;
for (int i = 0; i < _ARRAY_LEN(g_builtin_montserrat); i++) {
if (size == g_builtin_montserrat[i].size) {
return g_builtin_montserrat[i].font;
}
}
} else if (strcmp(name, "unscii") == 0) {
if (FONT_WEIGHT_NORMAL != weight)
return NULL;
#if LV_FONT_UNSCII_8
if (size == 8)
return &lv_font_unscii_8;
#endif
#if LV_FONT_UNSCII_16
if (size == 16)
return &lv_font_unscii_16;
#endif
}
#if LV_FONT_MONTSERRAT_12_SUBPX
else if (strcmp(name, "montserrat_subpx") == 0) {
if (size == 12)
return &lv_font_montserrat_12_subpx;
}
#endif
#if LV_FONT_DEJAVU_16_PERSIAN_HEBREW
else if (strcmp(name, "dejavu_persian_hebrew") == 0) {
if (size == 16)
return &lv_font_dejavu_16_persian_hebrew;
}
#endif
#if LV_FONT_SIMSUN_16_CJK
else if (strcmp(name, "dejavu_persian_hebrew") == 0) {
if (size == 16)
return &lv_font_simsun_16_cjk;
}
#endif
/* not built-in font, check extension */
luavgl_ctx_t *ctx = luavgl_context(L);
if (ctx->make_font) {
return ctx->make_font(name, size, weight);
}
return NULL;
}
/**
* Dynamic font family fallback is not supported.
* The fallback only happen when font creation fails and continue to try next
* one. Fallback logic in lvgl is supposed to be system wide.
*
* lvgl.Font("MiSansW medium, montserrat", 24, "normal")
*/
static int luavgl_font_create(lua_State *L)
{
int weight;
int size;
char *str, *name;
const lv_font_t *font = NULL;
if (!lua_isstring(L, 1)) {
return luaL_argerror(L, 1, "expect string");
}
/* size is optional, default to FONT_DEFAULT_SIZE */
size = lua_tointeger(L, 2);
if (size == 0) {
size = FONT_DEFAULT_SIZE;
}
if (!lua_isnoneornil(L, 3)) {
if (lua_isinteger(L, 3)) {
weight = lua_tointeger(L, 3);
} else {
char *luastr = (char *)lua_tostring(L, 3);
int len = strlen(luastr);
if (len > 128) {
/* not likely to happen */
return luaL_argerror(L, 3, "too long");
}
char s[len + 1];
strcpy(s, luastr);
weight = luavgl_get_named_weight(to_lower(s));
}
} else {
weight = FONT_WEIGHT_NORMAL;
}
str = strdup(lua_tostring(L, 1));
if (str == NULL) {
return luaL_error(L, "no memory.");
}
name = to_lower(str);
while (*name) {
if (*name == ' ') {
name++;
continue;
}
char *end = strchr(name, ',');
if (end != NULL) {
*end = '\0';
} else {
end = name + strlen(name);
}
char *trim = end - 1;
while (*trim == ' ') {
*trim-- = '\0'; /* trailing space. */
}
font = _luavgl_font_create(L, name, size, weight);
if (font) {
break;
}
name = end + 1; /* next */
}
free(str);
if (font) {
lua_pushlightuserdata(L, (void *)font);
return 1;
}
return luaL_error(L, "cannot create font.");
}
+383
View File
@@ -0,0 +1,383 @@
#include "luavgl.h"
#include "private.h"
typedef struct luavgl_fs_s {
lv_fs_file_t file;
bool closed; /* userdata exists but lv_fs has been closed */
} luavgl_fs_t;
typedef struct luavgl_dir_s {
lv_fs_dir_t dir;
bool closed; /* userdata exists but lv_fs has been closed */
} luavgl_dir_t;
static luavgl_fs_t *luavgl_to_fs(lua_State *L, int index)
{
luavgl_fs_t *v = luaL_checkudata(L, index, "lv_fs");
if (v->closed) {
luaL_error(L, "attempt to use a closed file");
}
return v;
}
static luavgl_dir_t *luavgl_to_dir(lua_State *L, int index)
{
luavgl_dir_t *v = luaL_checkudata(L, index, "lv_dir");
if (v->closed) {
luaL_error(L, "attempt to use a closed file");
}
return v;
}
/**
* luavgl.open_file(filename, [mode])
* mode: "r" "w", others not supported.
*/
static int luavgl_fs_open(lua_State *L)
{
const char *path = lua_tostring(L, 1);
const char *mode = "r";
if (lua_type(L, 2) == LUA_TSTRING) {
mode = lua_tostring(L, 2);
}
luavgl_fs_t *f = lua_newuserdata(L, sizeof(luavgl_fs_t));
f->closed = false;
lv_fs_mode_t lmode = 0;
if (strchr(mode, 'r'))
lmode |= LV_FS_MODE_RD;
if (strchr(mode, 'w'))
lmode |= LV_FS_MODE_WR;
lv_fs_res_t res = lv_fs_open(&f->file, path, lmode);
if (res != LV_FS_RES_OK) {
debug("open failed: %s\n", path);
lua_pushnil(L);
lua_pushfstring(L, "open failed: %s\n", path);
lua_pushinteger(L, res); /* return lv_fs error number */
return 3;
}
luaL_getmetatable(L, "lv_fs");
lua_setmetatable(L, -2);
return 1;
}
/* read_chars modified for lv_fs */
static int read_chars(lua_State *L, lv_fs_file_t *f, size_t n)
{
uint32_t nr; /* number of chars actually read */
char *p;
luaL_Buffer b;
luaL_buffinit(L, &b);
p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */
lv_fs_res_t res = lv_fs_read(f, p, n, &nr);
if (res != LV_FS_RES_OK)
return false;
luaL_pushresultsize(&b, nr);
return (nr > 0); /* true iff read something */
}
/* read_all modified for lv_fs */
static void read_all(lua_State *L, lv_fs_file_t *f)
{
uint32_t nr;
luaL_Buffer b;
luaL_buffinit(L, &b);
do { /* read file in chunks of LUAL_BUFFERSIZE bytes */
char *p = luaL_prepbuffer(&b);
lv_fs_read(f, p, LUAL_BUFFERSIZE, &nr);
luaL_addsize(&b, nr);
} while (nr == LUAL_BUFFERSIZE);
luaL_pushresult(&b); /* close buffer */
}
/**
* f:read()
*/
static int luavgl_fs_read(lua_State *L)
{
luavgl_fs_t *f = luavgl_to_fs(L, 1);
int nargs = lua_gettop(L) - 1;
int n, success;
if (nargs == 0)
return luaL_error(L, "read mode required: 'a' or num ");
/* ensure stack space for all results and for auxlib's buffer */
luaL_checkstack(L, nargs + LUA_MINSTACK, "too many arguments");
success = 1;
for (n = 2; nargs-- && success; n++) {
if (lua_type(L, n) == LUA_TNUMBER) {
size_t l = (size_t)luaL_checkinteger(L, n);
success = read_chars(L, &f->file, l);
} else {
const char *p = luaL_checkstring(L, n);
if (*p == '*')
p++; /* skip optional '*' (for compatibility) */
switch (*p) {
case 'a': /* file */
read_all(L, &f->file); /* read entire file */
success = 1; /* always success */
break;
case 'n': /* number */
case 'l': /* line */
case 'L': /* line with end-of-line */
default:
return luaL_argerror(L, n, "invalid format");
}
}
}
if (!success) {
lua_pop(L, 1); /* remove last result */
lua_pushnil(L); /* push nil instead */
}
return n - 2;
}
static int luavgl_fs_write(lua_State *L)
{
luavgl_fs_t *f = luavgl_to_fs(L, 1);
lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */
int arg = 2;
int nargs = lua_gettop(L) - arg;
int status = 1;
lv_fs_res_t res = 0;
size_t l;
uint32_t nw;
const char *s;
for (; nargs--; arg++) {
if (lua_type(L, arg) == LUA_TNUMBER) {
s = luaL_tolstring(L, arg, &l);
res = lv_fs_write(&f->file, s, l, &nw);
lua_pop(L, 1);
} else {
s = luaL_checklstring(L, arg, &l);
res = lv_fs_write(&f->file, s, l, &nw);
}
status = status && nw == l && res == LV_FS_RES_OK;
}
if (status) {
return 1; /* file handle already on stack top */
}
lua_pushnil(L);
lua_pushstring(L, "failed"); /* no details */
lua_pushinteger(L, res);
return 3;
}
static int luavgl_fs_close(lua_State *L)
{
luavgl_fs_t *f = luavgl_to_fs(L, 1);
debug("\n");
f->closed = true;
lv_fs_close(&f->file);
return 0;
}
static int luavgl_fs_seek(lua_State *L)
{
static const int mode[] = {LV_FS_SEEK_SET, LV_FS_SEEK_CUR, LV_FS_SEEK_END};
static const char *const modenames[] = {"set", "cur", "end", NULL};
luavgl_fs_t *f = luavgl_to_fs(L, 1);
int op = luaL_checkoption(L, 2, "cur", modenames);
lua_Integer p3 = luaL_optinteger(L, 3, 0);
uint32_t offset = (uint32_t)p3;
luaL_argcheck(L, (lua_Integer)offset == p3, 3,
"not an integer in proper range");
lv_fs_res_t res = lv_fs_seek(&f->file, offset, mode[op]);
if (res != LV_FS_RES_OK) {
lua_pushnil(L);
lua_pushstring(L, "failed");
lua_pushinteger(L, res);
return 3;
}
uint32_t pos;
res = lv_fs_tell(&f->file, &pos);
if (res != LV_FS_RES_OK) {
lua_pushinteger(L, 0);
} else {
lua_pushinteger(L, (lua_Integer)pos);
}
return 1;
}
static int luavgl_fs_tostring(lua_State *L)
{
lua_pushfstring(L, "lv_fs handler: %p\n", luavgl_to_fs(L, 1));
return 1;
}
static int luavgl_fs_gc(lua_State *L)
{
debug("\n");
luavgl_fs_t *v = luaL_checkudata(L, 1, "lv_fs");
if (!v->closed) {
v->closed = true;
lv_fs_close(&v->file);
}
return 0;
}
/**
* luavgl.open_dir(path)
*/
static int luavgl_dir_open(lua_State *L)
{
const char *path = lua_tostring(L, 1);
luavgl_dir_t *d = lua_newuserdata(L, sizeof(luavgl_dir_t));
d->closed = false;
lv_fs_res_t res = lv_fs_dir_open(&d->dir, path);
if (res != LV_FS_RES_OK) {
debug("open failed: %s\n", path);
lua_pushnil(L);
lua_pushfstring(L, "open failed: %s\n", path);
lua_pushinteger(L, res); /* return lv_fs error number */
return 3;
}
luaL_getmetatable(L, "lv_dir");
lua_setmetatable(L, -2);
return 1;
}
static int luavgl_dir_read(lua_State *L)
{
luavgl_dir_t *d = luavgl_to_dir(L, 1);
char buffer[PATH_MAX];
lv_fs_res_t res = lv_fs_dir_read(&d->dir, buffer);
if (res != LV_FS_RES_OK || buffer[0] == '\0') {
lua_pushnil(L);
} else {
lua_pushstring(L, buffer);
}
return 1;
}
static int luavgl_dir_close(lua_State *L)
{
debug("\n");
luavgl_dir_t *d = luavgl_to_dir(L, 1);
d->closed = true;
lv_fs_dir_close(&d->dir);
return 0;
}
static int luavgl_dir_tostring(lua_State *L)
{
lua_pushfstring(L, "lv_fs dir handler: %p\n", luavgl_to_dir(L, 1));
return 1;
}
static int luavgl_dir_gc(lua_State *L)
{
debug("\n");
luavgl_dir_t *v = luaL_checkudata(L, 1, "lv_dir");
if (!v->closed) {
v->closed = true;
lv_fs_dir_close(&v->dir);
}
return 0;
}
/**
* luavgl.fs lib
*
*/
static const luaL_Reg fs_lib[] = {
{"open_file", luavgl_fs_open },
{"open_dir", luavgl_dir_open},
{NULL, NULL },
};
/*
** methods for file handles
*/
static const luaL_Reg fs_methods[] = {
{"read", luavgl_fs_read },
{"write", luavgl_fs_write},
{"close", luavgl_fs_close},
{"seek", luavgl_fs_seek },
{NULL, NULL },
};
static const luaL_Reg fs_meta[] = {
{"__gc", luavgl_fs_gc },
{"__close", luavgl_fs_gc },
{"__tostring", luavgl_fs_tostring},
{"__index", NULL }, /* place holder */
{NULL, NULL }
};
/*
** methods for dir handles
*/
static const luaL_Reg dir_methods[] = {
{"read", luavgl_dir_read },
{"close", luavgl_dir_close},
{NULL, NULL },
};
static const luaL_Reg dir_meta[] = {
{"__gc", luavgl_dir_gc },
{"__close", luavgl_dir_gc },
{"__tostring", luavgl_dir_tostring},
{"__index", NULL }, /* place holder */
{NULL, NULL }
};
static void luavgl_fs_init(lua_State *L)
{
/* create lv_fs metatable */
luaL_newmetatable(L, "lv_fs");
luaL_setfuncs(L, fs_meta, 0);
luaL_newlib(L, fs_methods);
lua_setfield(L, -2, "__index");
lua_pop(L, 1); /* pop metatable */
/* create lv_dir metatable */
luaL_newmetatable(L, "lv_dir");
luaL_setfuncs(L, dir_meta, 0);
luaL_newlib(L, dir_methods);
lua_setfield(L, -2, "__index");
lua_pop(L, 1); /* pop metatable */
/* luavgl.fs lib */
luaL_newlib(L, fs_lib);
lua_setfield(L, -2, "fs");
}
+347
View File
@@ -0,0 +1,347 @@
#include "luavgl.h"
#include "private.h"
typedef struct luavgl_group_s {
lv_group_t *group;
bool lua_created; /* this group is created from lua */
bool deleted; /* deleted but not gc'ed */
} luavgl_group_t;
static luavgl_group_t *luavgl_check_group(lua_State *L, int idx)
{
luavgl_group_t *v = luaL_checkudata(L, idx, "lv_group");
if (v->deleted) {
luaL_error(L, "attempt to use a deleted group");
return NULL;
}
return v;
}
static lv_group_t *luavgl_to_group(lua_State *L, int idx)
{
return luavgl_check_group(L, idx)->group;
}
/**
* create new luavgl group userdata.
*/
static int luavgl_group_get(lua_State *L, lv_group_t *group)
{
/* check if already exists */
lua_pushlightuserdata(L, group);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
/* create new indev userdata and add to registry */
lua_pop(L, 1);
luavgl_group_t *g = lua_newuserdata(L, sizeof(luavgl_group_t));
g->deleted = false;
g->lua_created = true;
g->group = group;
luaL_getmetatable(L, "lv_group");
lua_setmetatable(L, -2);
lua_pushlightuserdata(L, group);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX);
}
return 1;
}
/**
* group = luavgl.group.create()
*/
static int luavgl_group_create(lua_State *L)
{
lv_group_t *group = lv_group_create();
return luavgl_group_get(L, group);
}
/**
* Delete a lua created group
*/
static int luavgl_group_delete(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
/* remove from registry */
lua_pushlightuserdata(L, g->group);
lua_pushnil(L);
lua_rawset(L, LUA_REGISTRYINDEX);
g->deleted = true;
#if 0
/* delete group if it's lua created. */
if (g->lua_created) {
lv_group_del(g->group);
g->group = NULL;
}
#else
/* delete the group anyway */
lv_group_del(g->group);
g->group = NULL;
#endif
debug("delete group:%p\n", g);
return 0;
}
/**
* group = luavgl.group.get_default()
*/
static int luavgl_group_get_default(lua_State *L)
{
lv_group_t *group = lv_group_get_default();
/* check if already exists */
lua_pushlightuserdata(L, group);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
lua_pop(L, 1);
luavgl_group_get(L, group);
luavgl_check_group(L, -1)->lua_created = false;
}
return 1;
}
static int luavgl_group_set_default(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
lv_group_set_default(g->group);
return 0;
}
static int luavgl_group_add_obj(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
lv_obj_t *obj = luavgl_to_obj(L, 2);
lv_group_add_obj(g->group, obj);
return 0;
}
static int luavgl_group_remove_objs(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
lv_group_remove_all_objs(g->group);
return 0;
}
static int luavgl_group_focus_next(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
lv_group_focus_next(g->group);
return 0;
}
static int luavgl_group_focus_prev(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
lv_group_focus_prev(g->group);
return 0;
}
static int luavgl_group_focus_freeze(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
bool en = luavgl_tointeger(L, 2);
lv_group_focus_freeze(g->group, en);
return 0;
}
static int luavgl_group_send_data(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
uint32_t c = luavgl_tointeger(L, 2);
lv_group_send_data(g->group, c);
return 0;
}
static int luavgl_group_set_focus_cb(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
(void)g;
return 0;
}
static int luavgl_group_set_edge_cb(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
(void)g;
return 0;
}
static int luavgl_group_get_focus_cb(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
(void)g;
return 0;
}
static int luavgl_group_get_edge_cb(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
(void)g;
return 0;
}
static int luavgl_group_set_editing(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
bool en = luavgl_tointeger(L, 2);
lv_group_set_editing(g->group, en);
return 0;
}
static int luavgl_group_set_wrap(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
bool en = luavgl_tointeger(L, 2);
lv_group_set_wrap(g->group, en);
return 0;
}
static int luavgl_group_get_wrap(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
bool en = lv_group_get_wrap(g->group);
lua_pushboolean(L, en);
return 1;
}
static int luavgl_group_get_obj_count(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
uint32_t count = lv_group_get_obj_count(g->group);
lua_pushinteger(L, count);
return 1;
}
static int luavgl_group_get_focused(lua_State *L)
{
luavgl_group_t *g = luavgl_check_group(L, 1);
lv_obj_t *obj = lv_group_get_focused(g->group);
if (obj == NULL) {
lua_pushnil(L);
} else {
lua_pushlightuserdata(L, obj);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
luavgl_add_lobj(L, obj)->lua_created = false;
}
}
return 1;
}
static int luavgl_group_remove_obj(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_group_remove_obj(obj);
return 0;
}
static int luavgl_group_focus_obj(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_group_focus_obj(obj);
return 0;
}
static int luavgl_group_gc(lua_State *L)
{
luavgl_group_t *g = luaL_checkudata(L, 1, "lv_group");
if (g->deleted) {
return 0;
}
#if 0
/* delete group if it's lua created. */
if (g->lua_created) {
lv_group_del(g->group);
g->group = NULL;
}
#else
/* delete the group anyway */
lv_group_del(g->group);
g->group = NULL;
#endif
debug("gc group: %p\n", g);
return 0;
}
/**
* luavgl.group lib
*/
static const luaL_Reg group_lib[] = {
{"create", luavgl_group_create },
{"get_default", luavgl_group_get_default},
{"remove_obj", luavgl_group_remove_obj },
{"remove_objs", luavgl_group_remove_objs},
{"focus_obj", luavgl_group_focus_obj },
{NULL, NULL },
};
/*
** methods for file handles
*/
static const luaL_Reg group_methods[] = {
{"delete", luavgl_group_delete },
{"set_default", luavgl_group_set_default },
{"add_obj", luavgl_group_add_obj },
{"remove_obj", luavgl_group_remove_obj },
{"focus_next", luavgl_group_focus_next },
{"focus_prev", luavgl_group_focus_prev },
{"focus_freeze", luavgl_group_focus_freeze },
{"send_data", luavgl_group_send_data },
{"set_focus_cb", luavgl_group_set_focus_cb },
{"set_edge_cb", luavgl_group_set_edge_cb },
{"get_focus_cb", luavgl_group_get_focus_cb },
{"get_edge_cb", luavgl_group_get_edge_cb },
{"set_editing", luavgl_group_set_editing },
{"set_wrap", luavgl_group_set_wrap },
{"get_wrap", luavgl_group_get_wrap },
{"get_obj_count", luavgl_group_get_obj_count},
{"get_focused", luavgl_group_get_focused },
{NULL, NULL },
};
static const luaL_Reg group_meta[] = {
{"__gc", luavgl_group_gc},
{"__index", NULL }, /* place holder */
{NULL, NULL }
};
static void luavgl_group_init(lua_State *L)
{
/* create lv_group metatable */
luaL_newmetatable(L, "lv_group");
luaL_setfuncs(L, group_meta, 0);
luaL_newlib(L, group_methods);
lua_setfield(L, -2, "__index");
lua_pop(L, 1); /* pop metatable */
/* luavgl.indev lib */
luaL_newlib(L, group_lib);
lua_setfield(L, -2, "group");
}
+342
View File
@@ -0,0 +1,342 @@
#include "luavgl.h"
#include "private.h"
typedef struct luavgl_indev_s {
lv_indev_t *indev;
} luavgl_indev_t;
/* group APIs */
static lv_group_t *luavgl_to_group(lua_State *L, int idx);
static luavgl_indev_t *luavgl_check_indev(lua_State *L, int idx)
{
luavgl_indev_t *v = luaL_checkudata(L, idx, "lv_indev");
if (v->indev == NULL) {
luaL_error(L, "null indev");
}
return v;
}
/**
* create new luavgl indev userdata.
*/
static int luavgl_indev_get(lua_State *L, lv_indev_t *indev)
{
if (indev == NULL) {
lua_pushnil(L);
return 1;
}
/* check if already exists */
lua_pushlightuserdata(L, indev);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
/* create new indev userdata and add to registry forever */
lua_pop(L, 1);
luavgl_indev_t *i = lua_newuserdata(L, sizeof(luavgl_indev_t));
i->indev = indev;
luaL_getmetatable(L, "lv_indev");
lua_setmetatable(L, -2);
lua_pushlightuserdata(L, indev);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX);
}
return 1;
}
static int luavgl_indev_get_act(lua_State *L)
{
lv_indev_t *indev = lv_indev_get_act();
return luavgl_indev_get(L, indev);
}
static int luavgl_indev_get_obj_act(lua_State *L)
{
lv_obj_t *obj = lv_indev_get_obj_act();
if (obj == NULL) {
lua_pushnil(L);
return 1;
}
/* registry[obj] */
lua_pushlightuserdata(L, obj);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
luavgl_add_lobj(L, obj)->lua_created = false;
}
return 1;
}
static int luavgl_indev_get_next(lua_State *L)
{
lv_indev_t *indev = NULL;
if (!lua_isnoneornil(L, 1)) {
indev = luavgl_check_indev(L, 1)->indev;
}
indev = lv_indev_get_next(indev);
return luavgl_indev_get(L, indev);
}
static int luavgl_indev_get_type(lua_State *L)
{
luavgl_indev_t *i = luavgl_check_indev(L, 1);
lv_indev_type_t t = lv_indev_get_type(i->indev);
lua_pushinteger(L, t);
return 1;
}
static int luavgl_indev_reset(lua_State *L)
{
luavgl_indev_t *i = luavgl_check_indev(L, 1);
lv_obj_t *obj = luavgl_to_obj(L, 2);
lv_indev_reset(i->indev, obj);
return 0;
}
static int luavgl_indev_reset_long_press(lua_State *L)
{
luavgl_indev_t *i = luavgl_check_indev(L, 1);
lv_indev_reset_long_press(i->indev);
return 1;
}
static int luavgl_indev_set_cursor(lua_State *L)
{
luavgl_indev_t *i = luavgl_check_indev(L, 1);
lv_obj_t *obj = luavgl_to_obj(L, 2);
lv_indev_set_cursor(i->indev, obj);
return 0;
}
static int luavgl_indev_set_group(lua_State *L)
{
luavgl_indev_t *i = luavgl_check_indev(L, 1);
lv_group_t *group = luavgl_to_group(L, 2);
lv_indev_set_group(i->indev, group);
return 0;
}
static int luavgl_indev_get_point(lua_State *L)
{
luavgl_indev_t *i = luavgl_check_indev(L, 1);
lv_point_t point;
lv_indev_get_point(i->indev, &point);
lua_pushinteger(L, point.x);
lua_pushinteger(L, point.y);
return 2;
}
static int luavgl_indev_get_gesture_dir(lua_State *L)
{
luavgl_indev_t *i = luavgl_check_indev(L, 1);
lv_dir_t dir = lv_indev_get_gesture_dir(i->indev);
lua_pushinteger(L, dir);
return 1;
}
static int luavgl_indev_get_key(lua_State *L)
{
luavgl_indev_t *i = luavgl_check_indev(L, 1);
uint32_t v = lv_indev_get_key(i->indev);
lua_pushinteger(L, v);
return 1;
}
static int luavgl_indev_get_scroll_dir(lua_State *L)
{
luavgl_indev_t *i = luavgl_check_indev(L, 1);
lv_dir_t dir = lv_indev_get_scroll_dir(i->indev);
lua_pushinteger(L, dir);
return 1;
}
static int luavgl_indev_get_scroll_obj(lua_State *L)
{
luavgl_indev_t *i = luavgl_check_indev(L, 1);
lv_obj_t *obj = lv_indev_get_scroll_obj(i->indev);
if (obj == NULL) {
lua_pushnil(L);
return 1;
}
/* registry[obj] */
lua_pushlightuserdata(L, obj);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
luavgl_add_lobj(L, obj)->lua_created = false;
}
return 1;
}
static int luavgl_indev_get_vect(lua_State *L)
{
luavgl_indev_t *i = luavgl_check_indev(L, 1);
lv_point_t point;
lv_indev_get_vect(i->indev, &point);
lua_pushinteger(L, point.x);
lua_pushinteger(L, point.y);
return 2;
}
static int luavgl_indev_wait_release(lua_State *L)
{
luavgl_indev_t *i = luavgl_check_indev(L, 1);
lv_indev_wait_release(i->indev);
return 0;
}
static void indev_feedback_cb(lv_indev_drv_t *driver, uint8_t code)
{
lua_State *L = driver->user_data;
int top = lua_gettop(L);
lua_pushlightuserdata(L, driver);
lua_rawget(L, LUA_REGISTRYINDEX); /* get indev on stack */
lua_getuservalue(L, -1); /* stack: indev, uservalue-table */
lua_rawgeti(L, -1, code); /* indev, uservalue, cb */
if (lua_isnoneornil(L, -1)) {
lua_settop(L, top);
return;
}
lua_pushvalue(L, 1);
lua_pushinteger(L, code);
luavgl_pcall_int(L, 2, 0);
lua_settop(L, top);
}
/**
* indev:on_event(code, cb)
*/
static int luavgl_indev_on_event(lua_State *L)
{
luavgl_indev_t *i = luavgl_check_indev(L, 1);
int code = lua_tointeger(L, 2);
luavgl_check_callable(L, 3);
lua_pushlightuserdata(L, i->indev->driver);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
lua_pop(L, 1);
/* set indev to registry using pointer as key */
lua_pushlightuserdata(L, i->indev->driver);
lua_pushvalue(L, 1);
lua_rawset(L, LUA_REGISTRYINDEX);
}
int type = lua_getuservalue(L, 1);
if (type != LUA_TTABLE) {
lua_pop(L, 1);
lua_createtable(L, 0, 1);
lua_pushvalue(L, -1);
lua_setuservalue(L, 1);
}
debug("add feedback_cb code %d, for indev->driver: %p\n", code,
i->indev->driver);
lua_pushvalue(L, 3);
lua_rawseti(L, -2, code);
i->indev->driver->feedback_cb = indev_feedback_cb;
i->indev->driver->user_data = L;
lua_settop(L, 1);
return 1;
}
static int luavgl_indev_tostring(lua_State *L)
{
lua_pushfstring(L, "lv_indev: %p\n", luavgl_check_indev(L, 1));
return 1;
}
static int luavgl_indev_gc(lua_State *L)
{
debug("\n");
/* If set_feedback_cb is used, then the indev only gets gc'ed when lua vm
* exits.
*/
luavgl_indev_t *i = luavgl_check_indev(L, 1);
lua_getuservalue(L, 1);
if (!lua_isnoneornil(L, -1)) {
lua_pushlightuserdata(L, i->indev->driver);
lua_pushnil(L);
lua_rawset(L, LUA_REGISTRYINDEX);
i->indev->driver->feedback_cb = NULL;
}
return 0;
}
/**
* luavgl.indev lib
*/
static const luaL_Reg indev_lib[] = {
{"get_act", luavgl_indev_get_act },
{"get_obj_act", luavgl_indev_get_obj_act},
{"get_next", luavgl_indev_get_next },
{NULL, NULL },
};
/*
** methods for file handles
*/
static const luaL_Reg methods[] = {
{"get_type", luavgl_indev_get_type },
{"reset", luavgl_indev_reset },
{"reset_long_press", luavgl_indev_reset_long_press},
{"set_cursor", luavgl_indev_set_cursor },
{"set_group", luavgl_indev_set_group },
{"get_point", luavgl_indev_get_point },
{"get_gesture_dir", luavgl_indev_get_gesture_dir },
{"get_key", luavgl_indev_get_key },
{"get_scroll_dir", luavgl_indev_get_scroll_dir },
{"get_scroll_obj", luavgl_indev_get_scroll_obj },
{"get_vect", luavgl_indev_get_vect },
{"wait_release", luavgl_indev_wait_release },
{"on_event", luavgl_indev_on_event },
{NULL, NULL },
};
static const luaL_Reg meta[] = {
{"__gc", luavgl_indev_gc },
{"__tostring", luavgl_indev_tostring},
{"__index", NULL }, /* place holder */
{NULL, NULL }
};
static void luavgl_indev_init(lua_State *L)
{
/* create lv_fs metatable */
luaL_newmetatable(L, "lv_indev");
luaL_setfuncs(L, meta, 0);
luaL_newlib(L, methods);
lua_setfield(L, -2, "__index");
lua_pop(L, 1); /* pop metatable */
/* luavgl.indev lib */
luaL_newlib(L, indev_lib);
lua_setfield(L, -2, "indev");
}
+150
View File
@@ -0,0 +1,150 @@
#include "luavgl.h"
#include "private.h"
#include "anim.c"
#include "constants.c"
#include "disp.c"
#include "font.c"
#include "fs.c"
#include "group.c"
#include "indev.c"
#include "obj.c"
#include "timer.c"
#include "util.c"
static const struct luaL_Reg luavgl_methods[] = {
{"Timer", luavgl_timer_create}, /* timer.c */
{"Font", luavgl_font_create }, /* font.c */
{"Style", luavgl_style_create}, /* style.c */
{"Anim", luavgl_anim_create }, /* anim.c */
{NULL, NULL },
};
LUALIB_API luavgl_ctx_t *luavgl_context(lua_State *L)
{
static const char *luavglgl_key = "luavgl_key";
luavgl_ctx_t *ctx;
lua_pushstring(L, luavglgl_key);
lua_rawget(L, LUA_REGISTRYINDEX);
/**
* ctx = registry[luavgl_key]
* if ctx == nil then
* ctx = new ctx
* else
* return ctx
* end
*/
if (lua_isnil(L, -1)) {
/* create it if not exist in registry */
lua_pushstring(L, luavglgl_key);
ctx = (luavgl_ctx_t *)lua_newuserdata(L, sizeof(*ctx));
memset(ctx, 0, sizeof(*ctx));
lua_rawset(L, LUA_REGISTRYINDEX);
} else {
ctx = (luavgl_ctx_t *)lua_touserdata(L, -1);
}
lua_pop(L, 1);
return ctx;
}
LUALIB_API void luavgl_set_pcall(lua_State *L, luavgl_pcall_t pcall)
{
luavgl_ctx_t *ctx = luavgl_context(L);
ctx->pcall = pcall;
}
LUALIB_API void luavgl_set_root(lua_State *L, lv_obj_t *root)
{
luavgl_ctx_t *ctx = luavgl_context(L);
ctx->root = root;
}
LUALIB_API void luavgl_set_font_extension(lua_State *L, make_font_cb make,
delete_font_cb d)
{
luavgl_ctx_t *ctx = luavgl_context(L);
ctx->make_font = make;
ctx->delete_font = d;
}
static int root_gc(lua_State *L)
{
debug("enter.\n");
luavgl_ctx_t *ctx = luavgl_context(L);
lv_obj_del(ctx->root);
return 0;
}
static int root_clean(lua_State *L)
{
debug("enter.\n");
luavgl_ctx_t *ctx = luavgl_context(L);
lv_obj_clean(ctx->root);
return 0;
}
LUALIB_API int luaopen_lvgl(lua_State *L)
{
luavgl_ctx_t *ctx = luavgl_context(L);
luaL_newlib(L, luavgl_methods);
luaL_newmetatable(L, "root.meta");
lua_pushstring(L, "__gc");
lua_pushcfunction(L, ctx->root ? root_clean : root_gc);
lua_settable(L, -3);
lua_pop(L, 1);
lv_obj_t *root = ctx->root;
if (root == NULL) {
debug("create root obj for lua.\n");
root = lv_obj_create(lv_scr_act());
ctx->root = root;
}
if (ctx->pcall == NULL)
ctx->pcall = luavgl_pcall;
lua_pushstring(L, "_root");
*(void **)lua_newuserdata(L, sizeof(void *)) = root;
luaL_getmetatable(L, "root.meta");
lua_setmetatable(L, -2);
/*
* create a ref to root, avoid __gc early
* this puts the root userdata into the _root key
* in the returned luv table
* */
lua_rawset(L, -3);
lv_obj_remove_style_all(root);
lv_obj_set_size(root, LV_HOR_RES, LV_VER_RES);
lv_obj_clear_flag(root, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE);
luavgl_obj_init(L);
luavgl_widgets_init(L);
luavgl_anim_init(L);
luavgl_timer_init(L);
luavgl_style_init(L);
luavgl_fs_init(L);
luavgl_indev_init(L);
luavgl_group_init(L);
luavgl_disp_init(L);
luavgl_constants_init(L);
/* Methods to create widget locate in widgets table, check `luavgl_obj_init`
*/
luaL_getmetatable(L, "widgets");
lua_setmetatable(L, -2);
(void)dumpstack;
(void)dumptable;
(void)dumpvalue;
return 1;
}
+263
View File
@@ -0,0 +1,263 @@
#pragma once
#include <lua.h>
#if (LUA_VERSION_NUM < 503)
#include "compat-5.3.h"
#endif
#include <lauxlib.h>
#include <lvgl.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef const lv_font_t *(*make_font_cb)(const char *name, int size,
int weight);
typedef void (*delete_font_cb)(const lv_font_t *);
typedef int (*luavgl_pcall_t)(lua_State *L, int nargs, int nresults);
typedef struct {
lv_obj_t *root;
make_font_cb make_font;
delete_font_cb delete_font;
luavgl_pcall_t pcall;
} luavgl_ctx_t;
typedef enum {
/* type can be regarded as int */
SETTER_TYPE_INT = 0,
SETTER_TYPE_COLOR,
SETTER_TYPE_STACK, /* parameter is on stack -1 */
SETTER_TYPE_POINTER, /* parameter from lightuserdata, a pointer */
SETTER_TYPE_IMGSRC,
} setter_type_t;
typedef void (*setter_int_t)(void *, int);
typedef void (*setter_pointer_t)(void *, void *);
typedef struct {
const char *key;
setter_type_t type;
union {
void (*setter)(void *, int);
void (*setter_stack)(void *, lua_State *L);
void (*setter_pointer)(void *, void *);
};
} luavgl_value_setter_t;
typedef struct luavgl_obj_s {
lv_obj_t *obj; /* NULL means obj deleted, but not gc'ed in lua */
bool lua_created; /* this object is created from lua */
/* internally used variables */
int n_events;
struct event_callback_s *events;
} luavgl_obj_t;
#define luavgl_obj_newmetatable(L, clz, name, l) \
luavgl_obj_createmetatable(L, clz, name, l, sizeof(l) / sizeof((l)[0]) - 1);
#define luavgl_set_property(L, obj, table) \
luavgl_set_property_array(L, obj, table, sizeof(table) / sizeof(table[0]))
LUALIB_API luavgl_ctx_t *luavgl_context(lua_State *L);
/**
* @brief set the protected call used in event callback.
* this must be called before luaopen_lvgl
*/
LUALIB_API void luavgl_set_pcall(lua_State *L, luavgl_pcall_t pcall);
/**
* @brief Set luavgl root object
*/
LUALIB_API void luavgl_set_root(lua_State *L, lv_obj_t *root);
/**
* @brief Set functions to make and destroy extended fonts.
*/
LUALIB_API void luavgl_set_font_extension(lua_State *L, make_font_cb make,
delete_font_cb d);
/* on embedded device, may call lib open manually. */
LUALIB_API int luaopen_lvgl(lua_State *L);
/* object creation */
/**
* @brief Helper function to create lua lvgl object.
*
* Expected stack layout:
* [1]: parent object
* [2]: table of properties(styles)
* Return value in stack:
* [1]: userdata of created object, luavgl object.
*
* @param L
* @param create function pointer to create object
* @return items in stack for return
*/
LUALIB_API int luavgl_obj_create_helper(lua_State *L,
lv_obj_t *(*create)(lv_obj_t *parent));
/**
* @brief Add existing lvgl object to lua
*
* Return value in stack:
* [1]: luavgl object.
*
* @return pointer to luavgl object
*/
LUALIB_API luavgl_obj_t *luavgl_add_lobj(lua_State *L, lv_obj_t *obj);
/**
* @brief Get lua lvgl object on stack
*
* Return value in stack:
* [1]: luavgl object.
*
* @return pointer to luavgl object
*/
LUALIB_API luavgl_obj_t *luavgl_to_lobj(lua_State *L, int idx);
/**
* @brief Create metatable for specified object class
*
* @param L
* @param clz object class
* @param name optional name for this metatable
* @param l methods for this metatable
* @param n methods length
*
* Return value in stack:
* [1]: metatable
*
* @return 1
*/
LUALIB_API int luavgl_obj_createmetatable(lua_State *L,
const lv_obj_class_t *clz,
const char *name, const luaL_Reg *l,
int n);
/**
* @brief Get user value of userdata of lua lvgl object, create if not exists
*
* @return type of the uservalue, LUA_TTABLE
*/
LUALIB_API int luavgl_obj_getuserdatauv(lua_State *L, int idx);
/* helper to get value from stack */
/**
* @brief Get lvgl object from stack
*/
LUALIB_API lv_obj_t *luavgl_to_obj(lua_State *L, int idx);
/**
* @brief Convert value to integer
*
* Supported values are: integer, float, boolean
*/
LUALIB_API int luavgl_tointeger(lua_State *L, int idx);
/**
* @brief Convert value to lvgl color
*
* Supported color formats are:
* [1]: string representation: "#RGB" or "#RRGGBB"
* [2]: integer value: 0xaabbcc
*/
LUALIB_API lv_color_t luavgl_tocolor(lua_State *L, int idx);
/**
* @brief Convert value to lvgl image source
*
* Supported image format:
* [1]: image path string, e.g. "/resource/bg.png"
* [2]: image source lightuserdata
*/
LUALIB_API const char *luavgl_toimgsrc(lua_State *L, int idx);
/**
* @brief Helper function to iterate through table
*
* @param L
* @param index index to the table for iteration
* @param cb callback function for every key,value pair
* Stack layout when cb function made:
* [-1]: value
* [-2]: key
* Care must be taken when calling lua_tostring etc. functions which will
* change stack layout.
* @param cb_param callback parameter passed to cb function
*/
LUALIB_API void luavgl_iterate(lua_State *L, int index,
int (*cb)(lua_State *, void *), void *cb_para);
/**
* @brief Set object property with provided setter functions
*
* @param L
* @param obj lvgl object
* @param table function array
* @param len functions in array
* @return 1
*/
LUALIB_API int luavgl_set_property_array(lua_State *L, void *obj,
const luavgl_value_setter_t table[],
uint32_t len);
/**
* @brief Dummy property set function
*/
LUALIB_API void _lv_dummy_set(void *obj, lua_State *L);
/**
* @brief Set object property with key,value in stack
*/
LUALIB_API int luavgl_obj_set_property_kv(lua_State *L, void *data);
/**
* @brief Set image property with key,value in stack
*/
LUALIB_API int luavgl_img_set_property_kv(lua_State *L, void *data);
LUALIB_API int luavgl_calendar_set_property_kv(lua_State *L, void *data);
LUALIB_API int luavgl_checkbox_set_property_kv(lua_State *L, void *data);
LUALIB_API int luavgl_dropdown_set_property_kv(lua_State *L, void *data);
LUALIB_API int luavgl_keyboard_set_property_kv(lua_State *L, void *data);
LUALIB_API int luavgl_label_set_property_kv(lua_State *L, void *data);
LUALIB_API int luavgl_led_set_property_kv(lua_State *L, void *data);
LUALIB_API int luavgl_list_set_property_kv(lua_State *L, void *data);
LUALIB_API int luavgl_roller_set_property_kv(lua_State *L, void *data);
LUALIB_API int luavgl_textarea_set_property_kv(lua_State *L, void *data);
/**
* @brief Protected call
* @return negative error code or zero.
*/
LUALIB_API int luavgl_pcall(lua_State *L, int nargs, int nresult);
/**
* @brief Check if lua object is callable.
* @return true if callable, false otherwise.
*/
LUALIB_API int luavgl_is_callable(lua_State *L, int index);
#ifdef __cplusplus
} /*extern "C"*/
#endif
File diff suppressed because it is too large Load Diff
+850
View File
@@ -0,0 +1,850 @@
#include "luavgl.h"
#include "private.h"
/* extended feature for object */
#include "event.c"
#include "style.c"
#include "widgets/widgets.c"
static int luavgl_anim_create(lua_State *L);
static int luavgl_obj_delete(lua_State *L);
static void _lv_obj_set_align(void *obj, lua_State *L)
{
if (lua_isinteger(L, -1)) {
lv_obj_align(obj, lua_tointeger(L, -1), 0, 0);
return;
}
if (!lua_istable(L, -1)) {
luaL_argerror(L, -1, "should be table.");
debug("para should be table.");
return;
}
lua_getfield(L, -1, "type");
lv_align_t align = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "x_ofs");
lv_coord_t x_ofs = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "y_ofs");
lv_coord_t y_ofs = lua_tointeger(L, -1);
lua_pop(L, 1);
lv_obj_align(obj, align, x_ofs, y_ofs);
}
/**
* @brief Set obj properties based on property table on stack top
*
* Internally used.
*/
static inline void luavgl_setup_obj(lua_State *L, lv_obj_t *obj)
{
luavgl_iterate(L, -1, luavgl_obj_set_property_kv, obj);
}
static void obj_delete_cb(lv_event_t *e)
{
lua_State *L = e->user_data;
lua_pushlightuserdata(L, e->current_target);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
goto pop_exit;
}
luavgl_obj_t *lobj = luavgl_to_lobj(L, -1);
if (lobj->lua_created)
goto pop_exit;
luavgl_obj_delete(L);
return;
pop_exit:
lua_pop(L, 1);
return;
}
/**
* get the obj userdata and uservalue, if uservalue is not a table, then add
* one. result stack: table(from uservalue)
* return uservalue type: LUA_TTABLE
*/
LUALIB_API int luavgl_obj_getuserdatauv(lua_State *L, int idx)
{
int type = lua_getuservalue(L, idx);
if (type == LUA_TTABLE)
return type;
lua_pop(L, 1);
/* initial element: 1 */
lua_createtable(L, 0, 1);
#if 0 /* reserved slot, not used for now */
lua_pushinteger(L, 1);
lua_pushnil(L);
lua_rawset(L, -3);
#endif
lua_pushvalue(L, -1); /* leave one on stack */
lua_setuservalue(L, idx > 0 ? idx : idx - 3);
return LUA_TTABLE;
}
static int luavgl_obj_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_obj_create);
}
static int luavgl_obj_delete(lua_State *L)
{
luavgl_obj_t *lobj;
/**
* Some widget may create child obj that doesn't belong to lua. Ignore them
* and report no error.
*/
if (!(lobj = lua_touserdata(L, -1))) {
return 0;
}
if (lobj->obj == NULL) {
/* could be already deleted, but not gc'ed */
return 0;
}
uint32_t cnt = lv_obj_get_child_cnt(lobj->obj);
for (int i = cnt - 1; i >= 0; i--) {
lv_obj_t *child = lv_obj_get_child(lobj->obj, i);
lua_checkstack(L, 2);
lua_pushlightuserdata(L, child);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
continue;
}
luavgl_obj_delete(L);
}
luavgl_obj_remove_event_all(L, lobj);
/* delete obj firstly, then cleanup memory */
if (lobj->lua_created) {
lv_obj_del(lobj->obj);
}
lua_checkstack(L, 2);
/* remove userdata from registry. */
lua_pushlightuserdata(L, lobj->obj);
lua_pushnil(L);
lua_rawset(L, LUA_REGISTRYINDEX);
debug("delete obj: %p\n", lobj->obj);
lobj->obj = NULL;
lua_pop(L, 1); /* remove the userdata para */
return 0;
}
static int luavgl_obj_clean(lua_State *L)
{
luavgl_obj_t *lobj = luavgl_to_lobj(L, -1);
if (lobj == NULL || lobj->obj == NULL)
return 0;
lv_obj_t *obj = lobj->obj;
uint32_t cnt = lv_obj_get_child_cnt(obj);
for (int i = cnt - 1; i >= 0; i--) {
lv_obj_t *child = lv_obj_get_child(obj, i);
lua_checkstack(L, 2);
lua_pushlightuserdata(L, child);
lua_rawget(L, LUA_REGISTRYINDEX);
luavgl_obj_delete(L);
}
lua_pop(L, 1); /* remove the userdata para */
return 0;
}
static int luavgl_obj_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_setup_obj(L, obj);
return 0;
}
/**
* obj:align_to({base=base, type=type, x_ofs=0, y_ofs=0})
*/
static int luavgl_obj_align_to(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, 2)) {
debug("para should be table.");
return luaL_argerror(L, 2, "should be table.");
}
lua_getfield(L, 2, "type");
lv_align_t align = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, 2, "base");
lv_obj_t *base = luavgl_to_lobj(L, -1)->obj;
lua_pop(L, 1);
if (base == NULL) {
debug("base is not lua obj");
return luaL_argerror(L, -1, "base is not lua obj");
}
lua_getfield(L, 2, "x_ofs");
lv_coord_t x_ofs = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, 2, "y_ofs");
lv_coord_t y_ofs = lua_tointeger(L, -1);
lua_pop(L, 1);
lv_obj_align_to(obj, base, align, x_ofs, y_ofs);
return 0;
}
static int luavgl_obj_set_parent(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_obj_t *parent = luavgl_to_obj(L, 2);
lv_obj_set_parent(obj, parent);
return 0;
}
static int luavgl_obj_get_screen(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_obj_t *screen = lv_obj_get_screen(obj);
/* check if userdata is added to this obj, so lua can access it. */
lua_pushlightuserdata(L, screen);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnil(L, -1)) {
/* create luavgl object and attach screen on it. */
luavgl_obj_t *lobj = luavgl_add_lobj(L, screen);
/* mark it's non-lua created, thus cannot be deleted by lua */
lobj->lua_created = false;
}
return 1;
}
static int luavgl_obj_get_parent(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_obj_t *parent = lv_obj_get_parent(obj);
/* check if userdata is added to this obj, so lua can access it. */
lua_pushlightuserdata(L, parent);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnil(L, -1)) {
/* create luavgl object and attach screen on it. */
luavgl_obj_t *lobj = luavgl_add_lobj(L, parent);
/* mark it's non-lua created, thus cannot be deleted by lua */
lobj->lua_created = false;
}
return 1;
}
static int luavgl_obj_set_get_parent(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_isnoneornil(L, 2)) {
lv_obj_t *parent = luavgl_to_obj(L, 2);
lv_obj_set_parent(obj, parent);
}
return luavgl_obj_get_parent(L);
}
static int luavgl_obj_get_child(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
int id = luavgl_tointeger(L, 2);
lv_obj_t *child = lv_obj_get_child(obj, id);
if (child == NULL) {
lua_pushnil(L);
return 1;
}
/* check if userdata is added to this obj, so lua can access it. */
lua_pushlightuserdata(L, child);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnil(L, -1)) {
luavgl_add_lobj(L, child)->lua_created = false;
}
return 1;
}
static int luavgl_obj_get_child_cnt(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushinteger(L, lv_obj_get_child_cnt(obj));
return 1;
}
static int luavgl_obj_get_state(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_state_t state = lv_obj_get_state(obj);
lua_pushinteger(L, state);
return 1;
}
/**
* obj:scroll_to({x=10})
* obj:scroll_to({x=10, anim=true})
* obj:scroll_to({x=10, y=100, anim=false})
*/
static int luavgl_obj_scroll_to(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_argerror(L, -1, "should be table {x=0,y=0,anim=true}");
}
lua_getfield(L, -1, "anim");
bool anim = luavgl_tointeger(L, -1);
lua_pop(L, 1);
lv_coord_t v;
lua_getfield(L, -1, "x");
if (!lua_isnil(L, -1)) {
v = lua_tointeger(L, -1);
lv_obj_scroll_to_x(obj, v, anim ? LV_ANIM_ON : LV_ANIM_OFF);
}
lua_pop(L, 1);
lua_getfield(L, -1, "y");
if (!lua_isnil(L, -1)) {
v = lua_tointeger(L, -1);
lv_obj_scroll_to_x(obj, v, anim ? LV_ANIM_ON : LV_ANIM_OFF);
}
lua_pop(L, 1);
return 0;
}
static int luavgl_obj_is_visible(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushboolean(L, lv_obj_is_visible(obj));
return 1;
}
static int luavgl_obj_add_flag(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_obj_flag_t flag = lua_tointeger(L, 2);
lv_obj_add_flag(obj, flag);
return 0;
}
static int luavgl_obj_clear_flag(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_obj_flag_t flag = lua_tointeger(L, 2);
lv_obj_clear_flag(obj, flag);
return 0;
}
static int luavgl_obj_add_state(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_state_t state = lua_tointeger(L, 2);
lv_obj_add_state(obj, state);
return 0;
}
static int luavgl_obj_clear_state(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_state_t state = lua_tointeger(L, 2);
lv_obj_clear_state(obj, state);
return 0;
}
/**
* obj:scroll_by(x, y, anim_en)
*/
static int luavgl_obj_scroll_by(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
int x = luavgl_tointeger(L, 2);
int y = luavgl_tointeger(L, 3);
int anim_en = luavgl_tointeger(L, 4);
lv_obj_scroll_by(obj, x, y, anim_en);
return 0;
}
static int luavgl_obj_scroll_by_bounded(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
int dx = luavgl_tointeger(L, 2);
int dy = luavgl_tointeger(L, 3);
int anim_en = luavgl_tointeger(L, 4);
lv_obj_scroll_by_bounded(obj, dx, dy, anim_en);
return 0;
}
static int luavgl_obj_scroll_to_view(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
int anim_en = luavgl_tointeger(L, 2);
lv_obj_scroll_to_view(obj, anim_en);
return 0;
}
static int luavgl_obj_scroll_to_view_recursive(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
int anim_en = luavgl_tointeger(L, 2);
lv_obj_scroll_to_view_recursive(obj, anim_en);
return 0;
}
static int luavgl_obj_scroll_by_raw(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
int x = luavgl_tointeger(L, 2);
int y = luavgl_tointeger(L, 3);
_lv_obj_scroll_by_raw(obj, x, y);
return 0;
}
static int luavgl_obj_is_scrolling(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushboolean(L, lv_obj_is_scrolling(obj));
return 1;
}
static int luavgl_obj_scrollbar_invalidate(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_obj_scrollbar_invalidate(obj);
return 0;
}
static int luavgl_obj_readjust_scroll(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
int anim_en = luavgl_tointeger(L, 2);
lv_obj_readjust_scroll(obj, anim_en);
return 0;
}
static int luavgl_obj_is_editable(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushboolean(L, lv_obj_is_editable(obj));
return 1;
}
static int luavgl_obj_is_group_def(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushboolean(L, lv_obj_is_group_def(obj));
return 1;
}
static int luavgl_obj_is_layout_positioned(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushboolean(L, lv_obj_is_layout_positioned(obj));
return 1;
}
static int luavgl_obj_mark_layout_as_dirty(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_obj_mark_layout_as_dirty(obj);
return 0;
}
static int luavgl_obj_center(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_obj_center(obj);
return 0;
}
static int luavgl_obj_invalidate(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_obj_invalidate(obj);
return 0;
}
static int luavgl_obj_set_flex_flow(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_flex_flow_t flow = luavgl_tointeger(L, 2);
lv_obj_set_flex_flow(obj, flow);
return 0;
}
static int luavgl_obj_set_flex_align(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_flex_align_t m = luavgl_tointeger(L, 2);
lv_flex_align_t c = luavgl_tointeger(L, 3);
lv_flex_align_t t = luavgl_tointeger(L, 4);
lv_obj_set_flex_align(obj, m, c, t);
return 0;
}
static int luavgl_obj_set_flex_grow(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
uint8_t grow = luavgl_tointeger(L, 2);
lv_obj_set_flex_grow(obj, grow);
return 0;
}
static int luavgl_obj_indev_search(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_point_t point;
if (lua_istable(L, 2)) {
lua_geti(L, 2, 1);
point.x = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_geti(L, 2, 2);
point.y = lua_tointeger(L, -1);
lua_pop(L, 1);
} else {
point.x = lua_tointeger(L, 2);
point.y = lua_tointeger(L, 3);
}
obj = lv_indev_search_obj(obj, &point);
if (obj == NULL) {
lua_pushnil(L);
} else {
lua_pushlightuserdata(L, obj);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
luavgl_add_lobj(L, obj)->lua_created = false;
}
}
return 1;
}
static int luavgl_obj_get_coords(lua_State *L)
{
lv_area_t area;
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_obj_get_coords(obj, &area);
lua_newtable(L);
lua_pushinteger(L, area.x1);
lua_setfield(L, -2, "x1");
lua_pushinteger(L, area.x2);
lua_setfield(L, -2, "x2");
lua_pushinteger(L, area.y1);
lua_setfield(L, -2, "y1");
lua_pushinteger(L, area.y2);
lua_setfield(L, -2, "y2");
return 1;
}
/**
* get object real position using lv_obj_get_x/x2/y/y2
*/
static int luavgl_obj_get_pos(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_newtable(L);
lua_pushinteger(L, lv_obj_get_x(obj));
lua_setfield(L, -2, "x1");
lua_pushinteger(L, lv_obj_get_x2(obj));
lua_setfield(L, -2, "x2");
lua_pushinteger(L, lv_obj_get_y(obj));
lua_setfield(L, -2, "y1");
lua_pushinteger(L, lv_obj_get_y2(obj));
lua_setfield(L, -2, "y2");
return 1;
}
/**
* Remove all animations associates to this object
*/
static int luavgl_obj_remove_anim_all(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_anim_del(obj, NULL);
return 1;
}
static int luavgl_obj_gc(lua_State *L)
{
if (lua_type(L, 1) != LUA_TUSERDATA) {
/* If t = setmetatable({}, obj_meta_table), this will happen when t is
* gc;ed. Currently all metatables for classes based on obj, that has no own
* __gc will goes here.
*/
return 0;
}
debug("\n");
luavgl_obj_t *lobj = lua_touserdata(L, 1);
if (lobj == NULL || lobj->obj == NULL) {
/* obj is already deleted. It's ok. */
return 0;
}
debug("GC for obj: %p\n", lobj->obj);
luavgl_obj_delete(L);
return 0;
}
static const luaL_Reg luavgl_obj_methods[] = {
{"set", luavgl_obj_set },
{"set_style", luavgl_obj_set_style },
{"align_to", luavgl_obj_align_to },
{"delete", luavgl_obj_delete },
{"clean", luavgl_obj_clean },
/* misc. functions */
{"parent", luavgl_obj_set_get_parent },
{"set_parent", luavgl_obj_set_parent },
{"get_parent", luavgl_obj_get_parent },
{"get_child", luavgl_obj_get_child },
{"get_child_cnt", luavgl_obj_get_child_cnt },
{"get_screen", luavgl_obj_get_screen },
{"get_state", luavgl_obj_get_state },
{"scroll_to", luavgl_obj_scroll_to },
{"is_scrolling", luavgl_obj_is_scrolling },
{"is_visible", luavgl_obj_is_visible },
{"add_flag", luavgl_obj_add_flag },
{"clear_flag", luavgl_obj_clear_flag },
{"add_state", luavgl_obj_add_state },
{"clear_state", luavgl_obj_clear_state },
{"add_style", luavgl_obj_add_style },
{"remove_style", luavgl_obj_remove_style },
{"remove_style_all", luavgl_obj_remove_style_all },
{"scroll_by", luavgl_obj_scroll_by },
{"scroll_by_bounded", luavgl_obj_scroll_by_bounded },
{"scroll_to_view", luavgl_obj_scroll_to_view },
{"scroll_to_view_recursive", luavgl_obj_scroll_to_view_recursive},
{"scroll_by_raw", luavgl_obj_scroll_by_raw },
{"scrollbar_invalidate", luavgl_obj_scrollbar_invalidate },
{"readjust_scroll", luavgl_obj_readjust_scroll },
{"is_editable", luavgl_obj_is_editable },
{"is_group_def", luavgl_obj_is_group_def },
{"is_layout_positioned", luavgl_obj_is_layout_positioned },
{"mark_layout_as_dirty", luavgl_obj_mark_layout_as_dirty },
{"center", luavgl_obj_center },
{"invalidate", luavgl_obj_invalidate },
{"set_flex_flow", luavgl_obj_set_flex_flow },
{"set_flex_align", luavgl_obj_set_flex_align },
{"set_flex_grow", luavgl_obj_set_flex_grow },
{"indev_search", luavgl_obj_indev_search },
{"get_coords", luavgl_obj_get_coords },
{"get_pos", luavgl_obj_get_pos },
{"onevent", luavgl_obj_on_event },
{"onPressed", luavgl_obj_on_pressed },
{"onClicked", luavgl_obj_on_clicked },
{"onShortClicked", luavgl_obj_on_short_clicked },
{"anim", luavgl_anim_create },
{"Anim", luavgl_anim_create },
{"remove_all_anim", luavgl_obj_remove_anim_all }, /* remove all */
{NULL, NULL },
};
static void luavgl_obj_init(lua_State *L)
{
/* base lv_obj */
luavgl_obj_newmetatable(L, &lv_obj_class, "lv_obj", luavgl_obj_methods);
lua_pushcfunction(L, luavgl_obj_gc);
lua_setfield(L, -2, "__gc");
/**
* Widget creation functions is a metatable, so we can add extended widget to
* it.
*
* widgets = {}
* lib = {widget_create_methods}
* widgets.__index = lib
* obj.__metatable = widgets
*/
lua_getfield(L, -1, "__index");
luaL_newmetatable(L, "widgets");
luaL_newlib(L, widget_create_methods);
lua_setfield(L, -2, "__index");
lua_setmetatable(L, -2);
lua_pop(L, 1); /* remove obj.__index table */
lua_pop(L, 1); /* remove obj metatable */
}
static const luavgl_value_setter_t obj_property_table[] = {
{"x", 0, {.setter = (setter_int_t)lv_obj_set_x} },
{"y", 0, {.setter = (setter_int_t)lv_obj_set_y} },
{"w", 0, {.setter = (setter_int_t)lv_obj_set_width} },
{"h", 0, {.setter = (setter_int_t)lv_obj_set_height} },
{"align", SETTER_TYPE_STACK, {.setter_stack = _lv_obj_set_align} },
{"scrollbar_mode", 0, {.setter = (setter_int_t)lv_obj_set_scrollbar_mode}},
{"scroll_dir", 0, {.setter = (setter_int_t)lv_obj_set_scroll_dir} },
{"scroll_snap_x", 0, {.setter = (setter_int_t)lv_obj_set_scroll_snap_x} },
{"scroll_snap_y", 0, {.setter = (setter_int_t)lv_obj_set_scroll_snap_y} },
};
/**
* Set object property.
* Differ from set object style, this one is usually used to set widget
* property like lv_WIDGETNAME_set_src()
*
* Used internally.
*
* Expected stack:
* stack[-2]: key(property name)
* stack[-1]: value(could be any lua data)
*/
LUALIB_API int luavgl_obj_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, obj_property_table);
if (ret == 0)
return 0;
/* fallback to set obj local style, with default state. */
return luavgl_obj_set_style_kv(L, obj, 0);
}
LUALIB_API int luavgl_obj_create_helper(lua_State *L,
lv_obj_t *(*create)(lv_obj_t *parent))
{
luavgl_ctx_t *ctx = luavgl_context(L);
lv_obj_t *parent;
if (lua_isnoneornil(L, 1)) {
parent = ctx->root;
} else {
parent = luavgl_to_obj(L, 1);
/* remove parent, in order to keep clean stack to call obj.set */
lua_remove(L, 1);
}
debug("create obj on: %p\n", parent);
lv_obj_t *obj = create(parent);
luavgl_add_lobj(L, obj)->lua_created = true;
if (!lua_istable(L, -2)) {
/* no need to call setup */
return 1;
}
lua_insert(L, -2); /* obj, prop */
/* now call obj.set to setup property */
lua_getfield(L, -2, "set"); /* obj, prop, set */
if (!luavgl_is_callable(L, -1)) {
/* set method not found, call basic obj set method. */
lua_pop(L, 2); /* remove prop table, and set method */
luavgl_setup_obj(L, obj);
} else {
lua_insert(L, -3); /* set, obj, prop */
lua_call(L, 2, 0); /* now stack is clean */
lua_pushlightuserdata(L, obj);
lua_rawget(L, LUA_REGISTRYINDEX);
}
debug("create obj: %p\n", obj);
return 1;
}
/**
* Add existing lvgl obj to lua, return lobj(luavgl obj).
* If no metatable not found for this obj class, then lv_obj_class metatable is
* used
*/
LUALIB_API luavgl_obj_t *luavgl_add_lobj(lua_State *L, lv_obj_t *obj)
{
luavgl_obj_t *lobj;
/* In rare case, obj may be deleted but not gc'ed in lua, and lvgl quickly
* creates another obj but happen to malloced same address, thus using obj
* light userdata as key may have some potential issues. */
lua_pushlightuserdata(L, obj);
lua_rawget(L, LUA_REGISTRYINDEX);
if (!lua_isnoneornil(L, -1)) {
/* already exists */
return luavgl_to_lobj(L, -1);
}
lua_pop(L, 1); /* pop nil value */
lobj = lua_newuserdata(L, sizeof(*lobj));
if (luavgl_obj_getmetatable(L, obj->class_p) == LUA_TNIL) {
lua_pop(L, 1);
debug("cannot find metatable for class: %p\n", obj->class_p);
/* use base obj metatable instead */
luavgl_obj_getmetatable(L, &lv_obj_class);
}
lua_setmetatable(L, -2);
memset(lobj, 0, sizeof(*lobj));
luavgl_obj_event_init(lobj);
lobj->obj = obj;
lv_obj_add_event_cb(obj, obj_delete_cb, LV_EVENT_DELETE, L);
/* registry[obj] = lobj */
lua_pushlightuserdata(L, obj);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX);
return lobj;
}
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include <lauxlib.h>
#include <lua.h>
#include <lvgl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
/* clang-format off */
#define debug(format, ...)
// fprintf(stderr, "[luavgl] %s: " format, __FUNCTION__, ##__VA_ARGS__)
// syslog(LOG_DEBUG, "[luavgl] %s: " format, __FUNCTION__, ##__VA_ARGS__)
/* clang-format on */
struct event_callback_s {
lv_event_code_t code;
struct _lv_event_dsc_t *dsc;
int ref; /* ref to callback */
}; /* variable array if n_callback > 1 */
static void dumpstack(lua_State *L);
static void dumptable(lua_State *L, int index);
/* metatable */
int luavgl_obj_getmetatable(lua_State *L, const lv_obj_class_t *clz);
int luavgl_obj_setmetatable(lua_State *L, int idx, const lv_obj_class_t *clz);
static void luavgl_obj_event_init(luavgl_obj_t *lobj);
static void luavgl_obj_remove_event_all(lua_State *L, luavgl_obj_t *obj);
/* util functions */
static void luavgl_check_callable(lua_State *L, int index);
static int luavgl_check_continuation(lua_State *L, int index);
static int luavgl_obj_set_style_kv(lua_State *L, lv_obj_t *obj, int selector);
static int luavgl_pcall_int(lua_State *L, int nargs, int nresult);
+702
View File
@@ -0,0 +1,702 @@
#include "luavgl.h"
#include "private.h"
typedef struct {
lv_style_t style;
} luavgl_style_t;
typedef enum {
STYLE_TYPE_INT = 1,
STYLE_TYPE_COLOR,
STYLE_TYPE_POINTER, /* a pointer from light-userdata */
STYLE_TYPE_IMGSRC, /* string or light-userdata, similar to pointer */
STYLE_TYPE_TABLE, /* value is in table */
/* Flag of none-simple type. All extended styles are special case. */
STYLE_TYPE_SPECIAL = 0x10,
} style_type_t;
enum {
LV_STYLE_SIZE = _LV_STYLE_LAST_BUILT_IN_PROP + 1,
LV_STYLE_PAD_ALL,
LV_STYLE_PAD_VER,
LV_STYLE_PAD_HOR,
LV_STYLE_PAD_GAP,
_LV_STYLE_FLEX,
_LV_STYLE_FLEX_FLOW, /* style not const, need to call related API */
_LV_STYLE_FLEX_MAIN_PLACE,
_LV_STYLE_FLEX_CROSS_PLACE,
_LV_STYLE_FLEX_TRACK_PLACE,
_LV_STYLE_FLEX_GROW,
};
/* callback made when style matched. */
typedef void (*style_set_cb_t)(lv_style_prop_t prop, lv_style_value_t value,
void *args);
static const struct style_map_s {
const char *name;
lv_style_prop_t prop;
style_type_t type;
} g_style_map[] = {
{"width", LV_STYLE_WIDTH, STYLE_TYPE_INT },
{"min_width", LV_STYLE_MIN_WIDTH, STYLE_TYPE_INT },
{"max_width", LV_STYLE_MAX_WIDTH, STYLE_TYPE_INT },
{"height", LV_STYLE_HEIGHT, STYLE_TYPE_INT },
{"min_height", LV_STYLE_MIN_HEIGHT, STYLE_TYPE_INT },
{"max_height", LV_STYLE_MAX_HEIGHT, STYLE_TYPE_INT },
{"x", LV_STYLE_X, STYLE_TYPE_INT },
{"y", LV_STYLE_Y, STYLE_TYPE_INT },
{"align", LV_STYLE_ALIGN, STYLE_TYPE_INT },
{"transform_width", LV_STYLE_TRANSFORM_WIDTH, STYLE_TYPE_INT },
{"transform_height", LV_STYLE_TRANSFORM_HEIGHT, STYLE_TYPE_INT },
{"translate_x", LV_STYLE_TRANSLATE_X, STYLE_TYPE_INT },
{"translate_y", LV_STYLE_TRANSLATE_Y, STYLE_TYPE_INT },
{"transform_zoom", LV_STYLE_TRANSFORM_ZOOM, STYLE_TYPE_INT },
{"transform_angle", LV_STYLE_TRANSFORM_ANGLE, STYLE_TYPE_INT },
{"transform_pivot_x", LV_STYLE_TRANSFORM_PIVOT_X, STYLE_TYPE_INT },
{"transform_pivot_y", LV_STYLE_TRANSFORM_PIVOT_Y, STYLE_TYPE_INT },
{"pad_top", LV_STYLE_PAD_TOP, STYLE_TYPE_INT },
{"pad_bottom", LV_STYLE_PAD_BOTTOM, STYLE_TYPE_INT },
{"pad_left", LV_STYLE_PAD_LEFT, STYLE_TYPE_INT },
{"pad_right", LV_STYLE_PAD_RIGHT, STYLE_TYPE_INT },
{"pad_row", LV_STYLE_PAD_ROW, STYLE_TYPE_INT },
{"pad_column", LV_STYLE_PAD_COLUMN, STYLE_TYPE_INT },
{"pad_gap", LV_STYLE_PAD_GAP, STYLE_TYPE_INT },
{"bg_color", LV_STYLE_BG_COLOR, STYLE_TYPE_COLOR },
{"bg_opa", LV_STYLE_BG_OPA, STYLE_TYPE_INT },
{"bg_grad_color", LV_STYLE_BG_GRAD_COLOR, STYLE_TYPE_COLOR },
{"bg_grad_dir", LV_STYLE_BG_GRAD_DIR, STYLE_TYPE_INT },
{"bg_main_stop", LV_STYLE_BG_MAIN_STOP, STYLE_TYPE_INT },
{"bg_grad_stop", LV_STYLE_BG_GRAD_STOP, STYLE_TYPE_INT },
{"bg_dither_mode", LV_STYLE_BG_DITHER_MODE, STYLE_TYPE_INT },
{"bg_img_src", LV_STYLE_BG_IMG_SRC, STYLE_TYPE_IMGSRC },
{"bg_img_opa", LV_STYLE_BG_IMG_OPA, STYLE_TYPE_INT },
{"bg_img_recolor", LV_STYLE_BG_IMG_RECOLOR, STYLE_TYPE_COLOR },
{"bg_img_recolor_opa", LV_STYLE_BG_IMG_RECOLOR_OPA, STYLE_TYPE_INT },
{"bg_img_tiled", LV_STYLE_BG_IMG_TILED, STYLE_TYPE_INT },
{"border_color", LV_STYLE_BORDER_COLOR, STYLE_TYPE_COLOR },
{"border_opa", LV_STYLE_BORDER_OPA, STYLE_TYPE_INT },
{"border_width", LV_STYLE_BORDER_WIDTH, STYLE_TYPE_INT },
{"border_side", LV_STYLE_BORDER_SIDE, STYLE_TYPE_INT },
{"border_post", LV_STYLE_BORDER_POST, STYLE_TYPE_INT },
{"outline_width", LV_STYLE_OUTLINE_WIDTH, STYLE_TYPE_INT },
{"outline_color", LV_STYLE_OUTLINE_COLOR, STYLE_TYPE_COLOR },
{"outline_opa", LV_STYLE_OUTLINE_OPA, STYLE_TYPE_INT },
{"outline_pad", LV_STYLE_OUTLINE_PAD, STYLE_TYPE_INT },
{"shadow_width", LV_STYLE_SHADOW_WIDTH, STYLE_TYPE_INT },
{"shadow_ofs_x", LV_STYLE_SHADOW_OFS_X, STYLE_TYPE_INT },
{"shadow_ofs_y", LV_STYLE_SHADOW_OFS_Y, STYLE_TYPE_INT },
{"shadow_spread", LV_STYLE_SHADOW_SPREAD, STYLE_TYPE_INT },
{"shadow_color", LV_STYLE_SHADOW_COLOR, STYLE_TYPE_COLOR },
{"shadow_opa", LV_STYLE_SHADOW_OPA, STYLE_TYPE_INT },
{"img_opa", LV_STYLE_IMG_OPA, STYLE_TYPE_INT },
{"img_recolor", LV_STYLE_IMG_RECOLOR, STYLE_TYPE_COLOR },
{"img_recolor_opa", LV_STYLE_IMG_RECOLOR_OPA, STYLE_TYPE_INT },
{"line_width", LV_STYLE_LINE_WIDTH, STYLE_TYPE_INT },
{"line_dash_width", LV_STYLE_LINE_DASH_WIDTH, STYLE_TYPE_INT },
{"line_dash_gap", LV_STYLE_LINE_DASH_GAP, STYLE_TYPE_INT },
{"line_rounded", LV_STYLE_LINE_ROUNDED, STYLE_TYPE_INT },
{"line_color", LV_STYLE_LINE_COLOR, STYLE_TYPE_INT },
{"line_opa", LV_STYLE_LINE_OPA, STYLE_TYPE_INT },
{"arc_width", LV_STYLE_ARC_WIDTH, STYLE_TYPE_INT },
{"arc_img_src", LV_STYLE_ARC_IMG_SRC, STYLE_TYPE_IMGSRC },
{"arc_rounded", LV_STYLE_ARC_ROUNDED, STYLE_TYPE_INT },
{"arc_color", LV_STYLE_ARC_COLOR, STYLE_TYPE_COLOR },
{"arc_opa", LV_STYLE_ARC_OPA, STYLE_TYPE_INT },
{"text_color", LV_STYLE_TEXT_COLOR, STYLE_TYPE_COLOR },
{"text_opa", LV_STYLE_TEXT_OPA, STYLE_TYPE_INT },
{"text_font", LV_STYLE_TEXT_FONT, STYLE_TYPE_POINTER }, /* light-userdata */
{"text_letter_space", LV_STYLE_TEXT_LETTER_SPACE, STYLE_TYPE_INT },
{"text_line_space", LV_STYLE_TEXT_LINE_SPACE, STYLE_TYPE_INT },
{"text_decor", LV_STYLE_TEXT_DECOR, STYLE_TYPE_INT },
{"text_align", LV_STYLE_TEXT_ALIGN, STYLE_TYPE_INT },
{"radius", LV_STYLE_RADIUS, STYLE_TYPE_INT },
{"clip_corner", LV_STYLE_CLIP_CORNER, STYLE_TYPE_INT },
{"opa", LV_STYLE_OPA, STYLE_TYPE_INT },
{"color_filter_opa", LV_STYLE_COLOR_FILTER_OPA, STYLE_TYPE_INT },
{"anim_time", LV_STYLE_ANIM_TIME, STYLE_TYPE_INT },
{"anim_speed", LV_STYLE_ANIM_SPEED, STYLE_TYPE_INT },
{"blend_mode", LV_STYLE_BLEND_MODE, STYLE_TYPE_INT },
{"layout", LV_STYLE_LAYOUT, STYLE_TYPE_INT },
{"base_dir", LV_STYLE_BASE_DIR, STYLE_TYPE_INT },
/* need to build pointer from table parameter */
{"bg_grad", LV_STYLE_BG_GRAD, STYLE_TYPE_SPECIAL }, /* pointer from table */
{"color_filter_dsc", LV_STYLE_COLOR_FILTER_DSC, STYLE_TYPE_SPECIAL }, /**/
{"anim", LV_STYLE_ANIM, STYLE_TYPE_SPECIAL }, /* anim para */
{"transition", LV_STYLE_TRANSITION, STYLE_TYPE_SPECIAL }, /* transition */
/* styles combined */
{"size", LV_STYLE_SIZE, STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
{"pad_all", LV_STYLE_PAD_ALL, STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
{"pad_ver", LV_STYLE_PAD_VER, STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
{"pad_hor", LV_STYLE_PAD_HOR, STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
/* styles for layout */
{"flex", _LV_STYLE_FLEX, STYLE_TYPE_SPECIAL | STYLE_TYPE_TABLE},
{"flex_flow", _LV_STYLE_FLEX_FLOW, STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
{"flex_main_place", _LV_STYLE_FLEX_MAIN_PLACE,
STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
{"flex_cross_place", _LV_STYLE_FLEX_CROSS_PLACE,
STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
{"flex_track_place", _LV_STYLE_FLEX_TRACK_PLACE,
STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
{"flex_grow", _LV_STYLE_FLEX_GROW, STYLE_TYPE_SPECIAL | STYLE_TYPE_INT },
};
#define STYLE_MAP_LEN (sizeof(g_style_map) / sizeof(g_style_map[0]))
/**
* lv_style
*/
static luavgl_style_t *luavgl_check_style(lua_State *L, int index)
{
luavgl_style_t *v = *(luavgl_style_t **)luaL_checkudata(L, index, "lv_style");
return v;
}
static void lv_style_set_cb(lv_style_prop_t prop, lv_style_value_t value,
void *args)
{
lv_style_t *s = args;
lv_style_set_prop(s, prop, value);
}
static void lv_style_set_inherit_cb(lv_style_prop_t prop,
lv_style_value_t value, void *args)
{
lv_style_t *s = args;
lv_style_set_prop_meta(s, prop, LV_STYLE_PROP_META_INHERIT);
}
static uint8_t to_int(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
return -1;
}
static lv_flex_align_t luavgl_to_flex_align(lua_State *L, int idx)
{
if (lua_type(L, idx) != LUA_TSTRING)
return LV_FLEX_ALIGN_START;
const char *str = lua_tostring(L, idx);
if (strcmp("flex-start", str) == 0)
return LV_FLEX_ALIGN_START;
if (strcmp("flex-end", str) == 0)
return LV_FLEX_ALIGN_END;
if (strcmp("center", str) == 0)
return LV_FLEX_ALIGN_CENTER;
if (strcmp("space-evenly", str) == 0)
return LV_FLEX_ALIGN_SPACE_EVENLY;
if (strcmp("space-around", str) == 0)
return LV_FLEX_ALIGN_SPACE_AROUND;
if (strcmp("space-between", str) == 0)
return LV_FLEX_ALIGN_SPACE_BETWEEN;
return LV_FLEX_ALIGN_START;
}
static int luavgl_set_flex_layout_kv(lua_State *L, style_set_cb_t cb,
void *args)
{
if (!lua_istable(L, -1)) {
debug("para should be table.");
return luaL_argerror(L, -1, "should be table.");
}
const char *str;
lv_flex_flow_t flow = LV_FLEX_FLOW_ROW;
lv_flex_align_t align;
/**
* flex-direction:
* row | row-reverse | column | column-reverse
*/
lua_getfield(L, -1, "flex_direction");
if (lua_type(L, -1) == LUA_TSTRING) {
str = lua_tostring(L, -1);
/* starts with */
if (strncmp("row", str, 3) == 0) {
flow = LV_FLEX_FLOW_ROW;
} else if (strncmp("column", str, 3) == 0) {
flow = LV_FLEX_FLOW_COLUMN;
}
/* if reverse presents */
if (strstr(str, "-reverse")) {
flow |= _LV_FLEX_REVERSE;
}
}
lua_pop(L, 1);
/**
* flex-wrap:
* nowrap | wrap | wrap-reverse;
*/
lua_getfield(L, -1, "flex_wrap");
if (lua_type(L, -1) == LUA_TSTRING) {
str = lua_tostring(L, -1);
if (strcmp("wrap", str) == 0) {
flow |= _LV_FLEX_WRAP;
} else if (strcmp("wrap-reverse", str) == 0) {
flow |= _LV_FLEX_WRAP | _LV_FLEX_REVERSE;
}
/* else: normal */
}
lua_pop(L, 1);
lv_style_value_t value = {0};
value.num = LV_LAYOUT_FLEX;
cb(LV_STYLE_LAYOUT, value, args);
value.num = flow;
cb(LV_STYLE_FLEX_FLOW, value, args);
/**
* justify-content
* flex-start | flex-end | center |
* space-between | space-around | space-evenly
*/
lua_getfield(L, -1, "justify_content");
if (lua_type(L, -1) == LUA_TSTRING) {
align = luavgl_to_flex_align(L, -1);
value.num = align;
cb(LV_STYLE_FLEX_MAIN_PLACE, value, args);
}
lua_pop(L, 1);
/**
* align-items
* flex-start | flex-end | center |
* space-between | space-around | space-evenly
*/
lua_getfield(L, -1, "align_items");
if (lua_type(L, -1) == LUA_TSTRING) {
align = luavgl_to_flex_align(L, -1);
value.num = align;
cb(LV_STYLE_FLEX_CROSS_PLACE, value, args);
}
lua_pop(L, 1);
/**
* align-content
* flex-start | flex-end | center |
* space-between | space-around | space-evenly
*/
lua_getfield(L, -1, "align_content");
if (lua_type(L, -1) == LUA_TSTRING) {
align = luavgl_to_flex_align(L, -1);
value.num = align;
cb(LV_STYLE_FLEX_TRACK_PLACE, value, args);
}
lua_pop(L, 1);
return 0;
}
/* is the style value on stack top is inherit special value */
static inline bool luavgl_is_style_inherit(lua_State *L)
{
const char *str;
return (lua_type(L, -1) == LUA_TSTRING) && (str = lua_tostring(L, -1)) &&
(strcmp(str, "inherit") == 0);
}
/**
* internal used API, called from style:set()
* key: stack[-2]
* value: stack[-1]
*
* @return 0 if succeed, -1 if failed.
*/
static int luavgl_set_style_kv(lua_State *L, style_set_cb_t cb, void *args)
{
const char *key = lua_tostring(L, -2);
if (key == NULL) {
debug("Null key, ignored.\n");
return -1;
}
/* map name to style value. */
lv_style_value_t value = {0};
const struct style_map_s *p = NULL;
for (int i = 0; i < STYLE_MAP_LEN; i++) {
if (strcmp(key, g_style_map[i].name) == 0) {
p = &g_style_map[i];
break;
}
}
if (p == NULL) /* not found */
return -1;
style_type_t type = p->type & 0x0f;
int v;
if (!luavgl_is_style_inherit(L)) {
/* get normal values */
switch (type) {
case STYLE_TYPE_INT:
v = luavgl_tointeger(L, -1);
value.num = v;
break;
case STYLE_TYPE_COLOR:
value.color = luavgl_tocolor(L, -1);
break;
case STYLE_TYPE_POINTER:
value.ptr = lua_touserdata(L, -1);
break;
case STYLE_TYPE_IMGSRC:
value.ptr = luavgl_toimgsrc(L, -1);
break;
case STYLE_TYPE_TABLE:
break;
default:
/* error, unkown type */
return luaL_error(L, "unknown style");
}
}
if (p->type & STYLE_TYPE_SPECIAL) {
switch ((int)p->prop) {
/* style combinations */
case LV_STYLE_SIZE:
cb(LV_STYLE_WIDTH, value, args);
cb(LV_STYLE_HEIGHT, value, args);
break;
case LV_STYLE_PAD_ALL:
cb(LV_STYLE_PAD_TOP, value, args);
cb(LV_STYLE_PAD_BOTTOM, value, args);
cb(LV_STYLE_PAD_LEFT, value, args);
cb(LV_STYLE_PAD_RIGHT, value, args);
break;
case LV_STYLE_PAD_VER:
cb(LV_STYLE_PAD_TOP, value, args);
cb(LV_STYLE_PAD_BOTTOM, value, args);
break;
case LV_STYLE_PAD_HOR:
cb(LV_STYLE_PAD_LEFT, value, args);
cb(LV_STYLE_PAD_RIGHT, value, args);
break;
case LV_STYLE_PAD_GAP:
cb(LV_STYLE_PAD_ROW, value, args);
cb(LV_STYLE_PAD_COLUMN, value, args);
break;
/* pointers needs to build from lua stack table */
case LV_STYLE_BG_GRAD:
break;
case LV_STYLE_COLOR_FILTER_DSC:
break;
case LV_STYLE_ANIM:
break;
case LV_STYLE_TRANSITION:
break;
/* layout styles that not constant */
case _LV_STYLE_FLEX_FLOW:
cb(LV_STYLE_FLEX_FLOW, value, args);
break;
case _LV_STYLE_FLEX_MAIN_PLACE:
cb(LV_STYLE_FLEX_MAIN_PLACE, value, args);
break;
case _LV_STYLE_FLEX_CROSS_PLACE:
cb(LV_STYLE_FLEX_CROSS_PLACE, value, args);
break;
case _LV_STYLE_FLEX_TRACK_PLACE:
cb(LV_STYLE_FLEX_TRACK_PLACE, value, args);
break;
case _LV_STYLE_FLEX_GROW:
cb(LV_STYLE_FLEX_GROW, value, args);
break;
case _LV_STYLE_FLEX: {
/* value is all on table */
luavgl_set_flex_layout_kv(L, cb, args);
break;
}
default:
break;
}
} else if (p->prop <= _LV_STYLE_LAST_BUILT_IN_PROP) {
cb(p->prop, value, args);
} else {
return luaL_error(L, "unknown style");
}
return 0;
}
/**
* style:set({x = 0, y = 0, bg_opa = 123})
*/
static int luavgl_style_set(lua_State *L)
{
luavgl_style_t *s = luavgl_check_style(L, 1);
if (!lua_istable(L, 2)) {
luaL_argerror(L, 2, "expect a table on 2nd para.");
return 0;
}
lua_pushnil(L); /* nil as initial key to iterate through table */
while (lua_next(L, -2)) {
/* -1: value, -2: key */
if (!lua_isstring(L, -2)) {
/* we expect string as key, ignore it if not */
debug("ignore non-string key in table.\n");
lua_pop(L, 1);
continue;
}
/* special value check */
bool inherit = luavgl_is_style_inherit(L);
luavgl_set_style_kv(L, inherit ? lv_style_set_inherit_cb : lv_style_set_cb,
s);
lua_pop(L, 1); /* remove value, keep the key to continue. */
}
return 0;
}
/**
* luavgl.Style({
* bg_color = 0xff0000,
* border_width = 1,
* })
*
* For simplicity, style need to be manually deleted `style:delete()` in order
* to be gc'ed.
*/
static int luavgl_style_create(lua_State *L)
{
luavgl_style_t *s = malloc(sizeof(luavgl_style_t));
if (s == NULL) {
return luaL_error(L, "No memory.");
}
lv_style_init(&s->style);
*(void **)lua_newuserdata(L, sizeof(void *)) = s;
luaL_getmetatable(L, "lv_style");
lua_setmetatable(L, -2);
lua_pushlightuserdata(L, s);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX);
lua_rotate(L, 1, 1); /* stack after: style-user-data, para */
luavgl_style_set(L);
lua_pop(L, 1); /* remove parameter table */
return 1;
}
/**
* style:remove_prop("width")
*/
static int luavgl_style_remove_prop(lua_State *L)
{
luavgl_style_t *s = luavgl_check_style(L, 1);
const char *name = lua_tostring(L, 2);
for (int i = 0; i < STYLE_MAP_LEN; i++) {
const struct style_map_s *p = &g_style_map[i];
if (strcmp(name, p->name) == 0) {
lv_style_remove_prop(&s->style, p->prop);
return 0;
}
}
return luaL_error(L, "unknown prop name: %s", name);
}
static int luavgl_style_delete(lua_State *L)
{
luavgl_style_t *s = luavgl_check_style(L, 1);
lua_pushlightuserdata(L, s);
lua_pushnil(L);
lua_rawset(L, LUA_REGISTRYINDEX);
return 1;
}
static int luavgl_style_gc(lua_State *L)
{
luavgl_style_t *s = luavgl_check_style(L, 1);
lv_style_reset(&s->style);
free(s);
debug("gc style:%p\n", s);
return 0;
}
/**
* lv_obj_style
*/
struct obj_style_s {
lv_obj_t *obj;
int selector;
};
static void obj_style_set_cb(lv_style_prop_t prop, lv_style_value_t value,
void *args)
{
struct obj_style_s *info = args;
lv_obj_set_local_style_prop(info->obj, prop, value, info->selector);
}
static void obj_style_inherit_set_cb(lv_style_prop_t prop,
lv_style_value_t value, void *args)
{
struct obj_style_s *info = args;
lv_obj_set_local_style_prop_meta(info->obj, prop, LV_STYLE_PROP_META_INHERIT,
info->selector);
}
static int luavgl_obj_set_style_kv(lua_State *L, lv_obj_t *obj, int selector)
{
struct obj_style_s info = {
.obj = obj,
.selector = selector,
};
/* special value check */
bool inherit = luavgl_is_style_inherit(L);
return luavgl_set_style_kv(
L, inherit ? obj_style_inherit_set_cb : obj_style_set_cb, &info);
}
/**
* obj:set_style({x = 0, y = 0, bg_opa = 123}, 0)
*/
static int luavgl_obj_set_style(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (obj == NULL) {
luaL_argerror(L, 1, "obj could already been deleted.");
return 0;
}
if (!lua_istable(L, 2)) {
luaL_argerror(L, 2, "expect a table on 2nd para.");
return 0;
}
int selector = 0;
if (!lua_isnoneornil(L, 3)) {
selector = lua_tointeger(L, 3);
lua_pop(L, 1); /* later we use stack[-1] to get table. */
}
lua_pushnil(L); /* nil as initial key to iterate through table */
while (lua_next(L, -2)) {
/* -1: value, -2: key */
if (!lua_isstring(L, -2)) {
/* we expect string as key, ignore it if not */
debug("ignore non-string key in table.\n");
lua_pop(L, 1);
continue;
}
luavgl_obj_set_style_kv(L, obj, selector);
lua_pop(L, 1); /* remove value, keep the key to continue. */
}
return 0;
}
/**
* obj:add_style(style, 0)
*/
static int luavgl_obj_add_style(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
luavgl_style_t *s = luavgl_check_style(L, 2);
int selector = 0;
if (!lua_isnoneornil(L, 3)) {
selector = lua_tointeger(L, 3);
}
lv_obj_add_style(obj, &s->style, selector);
return 0;
}
/**
* obj:remove_style(style, 0)
*/
static int luavgl_obj_remove_style(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
luavgl_style_t *s = luavgl_check_style(L, 2);
int selector = 0;
if (!lua_isnoneornil(L, 3)) {
selector = lua_tointeger(L, 3);
}
lv_obj_remove_style(obj, &s->style, selector);
return 0;
}
/**
* obj:remove_style_all()
*/
static int luavgl_obj_remove_style_all(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_obj_remove_style_all(obj);
return 0;
}
static const luaL_Reg luavgl_style_methods[] = {
{"set", luavgl_style_set },
{"delete", luavgl_style_delete },
{"remove_prop", luavgl_style_remove_prop},
{NULL, NULL }
};
static void luavgl_style_init(lua_State *L)
{
luaL_newmetatable(L, "lv_style");
lua_pushcfunction(L, luavgl_style_gc);
lua_setfield(L, -2, "__gc");
luaL_newlib(L, luavgl_style_methods); /* methods belong to this type */
lua_setfield(L, -2, "__index");
lua_pop(L, 1); /* pop __index table */
}
+222
View File
@@ -0,0 +1,222 @@
#include "luavgl.h"
#include "private.h"
typedef struct luavgl_timer_s {
lua_State *L;
int ref; /* ref to callback */
} luavgl_timer_t;
static lv_timer_t *luavgl_check_timer(lua_State *L, int index)
{
lv_timer_t *v = *(lv_timer_t **)luaL_checkudata(L, index, "lv_timer");
return v;
}
static void luavgl_timer_cb(lv_timer_t *t)
{
luavgl_timer_t *data = t->user_data;
lua_State *L = data->L;
int ref = data->ref;
if (ref == LUA_NOREF) {
return;
}
int top = lua_gettop(L);
/* stack: 1. function, 2. timer userdata */
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
lua_pushlightuserdata(L, t);
lua_rawget(L, LUA_REGISTRYINDEX); /* this should not fail*/
luavgl_pcall_int(L, 1, 0);
lua_settop(L, top);
}
static void luavgl_timer_set_cb(void *_t, lua_State *L)
{
lv_timer_t *t = _t;
int ref = luavgl_check_continuation(L, -1);
luavgl_timer_t *data = t->user_data;
if (data->ref != LUA_NOREF) {
luaL_unref(L, LUA_REGISTRYINDEX, data->ref);
}
data->ref = ref;
}
static void luavgl_timer_set_paused(lv_timer_t *t, int paused)
{
/* pause or resume. */
paused ? lv_timer_pause(t) : lv_timer_resume(t);
}
/* clang-format off */
static const luavgl_value_setter_t timer_property_table[] = {
{ "paused", 0, { .setter = (setter_int_t)luavgl_timer_set_paused } },
{ "period", 0, { .setter = (setter_int_t)lv_timer_set_period } },
{ "repeat_count", 0, { .setter = (setter_int_t)lv_timer_set_repeat_count } },
{ "cb", SETTER_TYPE_STACK, { .setter_stack = luavgl_timer_set_cb } },
};
/* clang-format on */
static int timer_set_para_cb(lua_State *L, void *data)
{
int ret = luavgl_set_property(L, data, timer_property_table);
if (ret != 0) {
debug("failed\n");
}
return ret;
}
/* setup timer using parameter in table idx */
int luavgl_timer_setup(lua_State *L, int idx, lv_timer_t *t)
{
luavgl_iterate(L, idx, timer_set_para_cb, t);
return 1;
}
/**
* t = luavgl:timer({timer parameters})
* t:pause()
* t:resume()
* t:ready() -- make it ready right now
*
*/
static int luavgl_timer_create(lua_State *L)
{
luavgl_timer_t *data = malloc(sizeof(luavgl_timer_t));
if (data == NULL) {
return luaL_error(L, "No memory.");
}
data->ref = LUA_NOREF;
data->L = L;
lv_timer_t *t = lv_timer_create(luavgl_timer_cb, 0, data);
*(void **)lua_newuserdata(L, sizeof(void *)) = t;
luaL_getmetatable(L, "lv_timer");
lua_setmetatable(L, -2);
lua_pushlightuserdata(L, t);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX);
/* parameter table is on stack[1] */
luavgl_timer_setup(L, 1, t);
lua_remove(L, 1); /* remove it to keep stack balance */
if (t->period == 0) {
/* if period is not set, then it's paused. */
lv_timer_pause(t);
}
return 1;
}
static int luavgl_timer_set(lua_State *L)
{
lv_timer_t *t = luavgl_check_timer(L, 1);
if (t == NULL) {
return luaL_argerror(L, 1, "timer is null.");
}
luavgl_timer_setup(L, 2, t);
return 0;
}
static int luavgl_timer_ready(lua_State *L)
{
lv_timer_t *t = luavgl_check_timer(L, 1);
if (t == NULL) {
return luaL_argerror(L, 1, "timer is null.");
}
lv_timer_ready(t);
return 0;
}
static int luavgl_timer_resume(lua_State *L)
{
lv_timer_t *t = luavgl_check_timer(L, 1);
if (t == NULL) {
return luaL_argerror(L, 1, "timer is null.");
}
lv_timer_resume(t);
return 0;
}
static int luavgl_timer_pause(lua_State *L)
{
lv_timer_t *t = luavgl_check_timer(L, 1);
if (t == NULL) {
return luaL_argerror(L, 1, "timer is null.");
}
lv_timer_pause(t);
return 0;
}
/* remove timer from obj, */
static int luavgl_timer_delete(lua_State *L)
{
lv_timer_t *t = luavgl_check_timer(L, 1);
if (t == NULL) {
return luaL_argerror(L, 1, "timer is null.");
}
luavgl_timer_t *data = t->user_data;
if (data->ref) {
luaL_unref(L, LUA_REGISTRYINDEX, data->ref);
data->ref = LUA_NOREF;
}
lua_pushlightuserdata(L, t);
lua_pushnil(L);
lua_rawset(L, LUA_REGISTRYINDEX);
/* we can only release memory in gc, since we need t->use_data */
lv_timer_pause(t);
debug("delete timer:%p\n", t);
return 0;
}
static int luavgl_timer_gc(lua_State *L)
{
/* stop timer if not stopped. */
luavgl_timer_delete(L);
lv_timer_t *t = luavgl_check_timer(L, 1);
free(t->user_data);
lv_timer_del(t);
debug("gc timer:%p\n", t);
return 0;
}
static const luaL_Reg luavgl_timer_methods[] = {
{"set", luavgl_timer_set },
{"pause", luavgl_timer_pause },
{"resume", luavgl_timer_resume},
{"delete", luavgl_timer_delete},
{"ready", luavgl_timer_ready },
{NULL, NULL }
};
static void luavgl_timer_init(lua_State *L)
{
luaL_newmetatable(L, "lv_timer");
lua_pushcfunction(L, luavgl_timer_gc);
lua_setfield(L, -2, "__gc");
luaL_newlib(L, luavgl_timer_methods); /* methods belong to this type */
lua_setfield(L, -2, "__index");
lua_pop(L, 1); /* pop __index table */
}
+413
View File
@@ -0,0 +1,413 @@
#include "luavgl.h"
#include "private.h"
LUALIB_API luavgl_obj_t *luavgl_to_lobj(lua_State *L, int idx)
{
luavgl_obj_t *lobj = lua_touserdata(L, idx);
if (lobj == NULL) {
goto fail;
}
if (lobj->obj == NULL) {
/* could be already deleted, but not gc'ed */
return NULL;
}
return lobj;
fail:
debug("arg not lv_obj userdata.\n");
luaL_argerror(L, idx, "Expected lv_obj userdata");
return NULL;
}
LUALIB_API int luavgl_is_callable(lua_State *L, int index)
{
if (luaL_getmetafield(L, index, "__call") != LUA_TNIL) {
/* getmetatable(x).__call must be a function for x() to work */
int callable = lua_isfunction(L, -1);
lua_pop(L, 1);
return callable;
}
return lua_isfunction(L, index);
}
static void luavgl_check_callable(lua_State *L, int index)
{
if (luavgl_is_callable(L, index))
return;
luaL_argerror(L, index, "function or callable table expected");
}
static int luavgl_check_continuation(lua_State *L, int index)
{
if (lua_isnoneornil(L, index))
return LUA_NOREF;
luavgl_check_callable(L, index);
lua_pushvalue(L, index);
return luaL_ref(L, LUA_REGISTRYINDEX);
}
static void dumpvalue(lua_State *L, int i, bool cr)
{
const char ending = cr ? '\n' : '\0';
switch (lua_type(L, i)) {
case LUA_TNUMBER:
printf("number: %g%c", lua_tonumber(L, i), ending);
break;
case LUA_TSTRING:
printf("string: %s%c", lua_tostring(L, i), ending);
break;
case LUA_TBOOLEAN:
printf("boolean: %s%c", (lua_toboolean(L, i) ? "true" : "false"), ending);
break;
case LUA_TNIL:
printf("nil: %s%c", "nil", ending);
break;
default:
printf("pointer: %p%c", lua_topointer(L, i), ending);
break;
}
}
static void dumptable(lua_State *L, int index)
{
int i = index < 0 ? index - 1 : index;
lua_pushnil(L); /* nil as initial key to iterate through table */
while (lua_next(L, i)) {
/* -1: value, -2: key */
dumpvalue(L, -2, 0);
printf(" ");
dumpvalue(L, -1, 1);
lua_pop(L, 1); /* remove value, keep the key to continue. */
}
fflush(stdout);
}
static void dumpstack(lua_State *L)
{
int top = lua_gettop(L);
printf("\n");
for (int i = 1; i <= top; i++) {
printf("%d\t%s\t", i, luaL_typename(L, i));
switch (lua_type(L, i)) {
case LUA_TNUMBER:
printf("number: %g\n", lua_tonumber(L, i));
break;
case LUA_TSTRING:
printf("string: %s\n", lua_tostring(L, i));
break;
case LUA_TBOOLEAN:
printf("boolean: %s\n", (lua_toboolean(L, i) ? "true" : "false"));
break;
case LUA_TNIL:
printf("nil: %s\n", "nil");
break;
default:
printf("pointer: %p\n", lua_topointer(L, i));
break;
}
}
fflush(stdout);
}
/**
* Create a table(used as object metatable), using clz as key in lua
* registry. The name is set to metatable.__name if not NULL
*/
LUALIB_API int luavgl_obj_createmetatable(lua_State *L,
const lv_obj_class_t *clz,
const char *name, const luaL_Reg *l,
int n)
{
if (luavgl_obj_getmetatable(L, clz) != LUA_TNIL) /* meta already exists */
return 0; /* leave previous value on top, but return 0 */
lua_pop(L, 1);
/* create metatable, 4 elements, normally for __magic, __index, __gc and
* __name. */
lua_createtable(L, 0, 4);
if (name) {
lua_pushstring(L, name);
lua_setfield(L, -2, "__name"); /* metatable.__name = tname */
}
/** A magic string we used to check if userdata is a luavgl object. */
lua_pushstring(L, "luavglObj");
lua_setfield(L, -2, "__magic");
/* add to registry */
lua_pushlightuserdata(L, (void *)clz);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX); /* registry[clz] = metatable */
/* New index table.
* M = {} -- stack top
*
* t = {l} -- table contains the lib functions
* b = getmatatable(clz.base_clz)
* setmetatable(t, b)
* M.__index = t
*/
lua_createtable(L, 0, n); /* t = {} */
luaL_setfuncs(L, l, 0); /* set methods to t */
if (clz != &lv_obj_class) {
/* b = getmatatable(clz.base_clz) */
if (luavgl_obj_getmetatable(L, clz->base_class) == LUA_TNIL) {
return luaL_error(L, "need to init base class firstly: %s.", name);
}
/* setmetatable(t, b) */
lua_setmetatable(L, -2);
}
lua_setfield(L, -2, "__index"); /* M.__index = t */
return 1;
}
int luavgl_obj_getmetatable(lua_State *L, const lv_obj_class_t *clz)
{
lua_pushlightuserdata(L, (void *)clz);
return lua_rawget(L, LUA_REGISTRYINDEX);
}
/**
* get metatable of clz, and set it as the metatable of table on stack idx
* return 0 if failed.
*/
int luavgl_obj_setmetatable(lua_State *L, int idx, const lv_obj_class_t *clz)
{
if (luavgl_obj_getmetatable(L, clz) == LUA_TNIL) {
lua_pop(L, 1);
return 0;
}
lua_setmetatable(L, idx);
return 1;
}
static int msghandler(lua_State *L)
{
if (!lua_isstring(L, 1)) /* 'message' not a string? */
return 1; /* keep it intact */
const char *msg = lua_tostring(L, 1);
if (msg == NULL) { /* is error object not a string? */
if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */
lua_type(L, -1) == LUA_TSTRING) /* that produces a string? */
return 1; /* that is the message */
else
msg = lua_pushfstring(L, "(error object is a %s value)",
luaL_typename(L, 1));
}
/* append a standard traceback */
luaL_traceback(L, L, msg, 1);
/* show it on screen */
lv_obj_t *root = NULL;
luavgl_ctx_t *ctx = luavgl_context(L);
root = lv_obj_create(ctx->root ? ctx->root : lv_scr_act());
lv_obj_set_size(root, LV_PCT(80), LV_PCT(80));
lv_obj_center(root);
lv_obj_set_style_bg_color(root, lv_color_black(), 0);
lv_obj_set_style_bg_opa(root, LV_OPA_70, 0);
lv_obj_set_style_border_width(root, 1, 0);
lv_obj_t *label = lv_label_create(root);
lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP);
lv_obj_set_style_text_font(label, LV_FONT_DEFAULT, 0);
lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_LIGHT_GREEN),
0);
lv_obj_set_width(label, LV_PCT(80));
lv_obj_center(label);
lv_label_set_text(label, lua_tostring(L, -1));
return 1;
}
LUALIB_API int luavgl_pcall(lua_State *L, int nargs, int nresult)
{
int base = lua_gettop(L) - nargs; /* function index */
lua_pushcfunction(L, msghandler); /* push message handler */
lua_insert(L, base); /* put it under function and args */
int status = lua_pcall(L, nargs, nresult, base);
if (status != LUA_OK) {
debug("crashed\n%s", lua_tostring(L, -1));
}
lua_remove(L, base); /* remove message handler from the stack */
return status;
}
LUALIB_API void *luavgl_test_obj(lua_State *L, int ud)
{
void *p = lua_touserdata(L, ud);
if (p != NULL) { /* value is a userdata? */
if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
lua_getfield(L, -1, "__magic"); /* get the magic string */
lua_pushstring(L, "luavglObj");
/* strings are interned, so no need to use strcmp. */
if (!lua_rawequal(L, -1, -2)) /* not the same? */
p = NULL; /* value is a userdata with wrong metatable */
lua_pop(L, 3); /* remove metatable and two strings */
return p;
}
}
return NULL; /* value is not a userdata with a metatable */
}
LUALIB_API lv_obj_t *luavgl_to_obj(lua_State *L, int idx)
{
luavgl_obj_t *lobj = luavgl_test_obj(L, idx);
if (lobj == NULL || lobj->obj == NULL) {
luaL_argerror(L, idx, "expect lua lvgl object, got null");
return NULL;
}
return lobj->obj;
}
LUALIB_API int luavgl_tointeger(lua_State *L, int idx)
{
int v = 0;
if (lua_isboolean(L, idx)) {
v = lua_toboolean(L, idx);
} else if (lua_isinteger(L, idx)) {
v = lua_tointeger(L, idx);
} else {
v = lua_tonumber(L, idx);
}
return v;
}
LUALIB_API lv_color_t luavgl_tocolor(lua_State *L, int idx)
{
lv_color_t color = {0};
if (lua_type(L, idx) == LUA_TSTRING) {
/* support #RGB and #RRGGBB */
const char *s = lua_tostring(L, idx);
if (s == NULL) {
luaL_error(L, "unknown color.");
return color;
}
int len = strlen(s);
if (len == 4 && s[0] == '#') {
/* #RGB */
int r = to_int(s[1]);
r |= r << 4;
int g = to_int(s[2]);
g |= g << 4;
int b = to_int(s[3]);
b |= b << 4;
color = lv_color_make(r, g, b);
} else if (len == 7 && s[0] == '#') {
/* #RRGGBB */
int r = (to_int(s[1]) << 4) | to_int(s[2]);
int g = (to_int(s[3]) << 4) | to_int(s[4]);
int b = (to_int(s[5]) << 4) | to_int(s[6]);
color = lv_color_make(r, g, b);
} else {
luaL_error(L, "unknown color format.");
return color;
}
} else {
color = lv_color_hex(luavgl_tointeger(L, idx)); /* make to lv_color_t */
}
return color;
}
LUALIB_API const char *luavgl_toimgsrc(lua_State *L, int idx)
{
const char *src = NULL;
if (lua_isuserdata(L, idx)) {
src = lua_touserdata(L, idx);
debug("set img src to user data: %p\n", src);
} else if (lua_isstring(L, idx)) {
src = lua_tostring(L, idx);
} else {
debug("img src should be string or userdata.\n");
return NULL;
}
return src;
}
LUALIB_API void luavgl_iterate(lua_State *L, int index,
int (*cb)(lua_State *, void *), void *cb_para)
{
int i = index < 0 ? index - 1 : index;
lua_pushnil(L); /* nil as initial key to iterate through table */
while (lua_next(L, i)) {
/* -1: value, -2: key */
if (!lua_isstring(L, -2)) {
/* we expect string as key, ignore it if not */
debug("ignore non-string key in table.\n");
lua_pop(L, 1);
continue;
}
cb(L, cb_para);
lua_pop(L, 1); /* remove value, keep the key to continue. */
}
}
LUALIB_API int luavgl_set_property_array(lua_State *L, void *obj,
const luavgl_value_setter_t table[],
uint32_t len)
{
const char *key = lua_tostring(L, -2);
if (key == NULL) {
debug("Null key, ignored.\n");
return -1;
}
for (int i = 0; i < len; i++) {
const luavgl_value_setter_t *p = &table[i];
if (strcmp(key, p->key))
continue;
if (p->type == SETTER_TYPE_INT) {
int v;
if (lua_isboolean(L, -1)) {
v = lua_toboolean(L, -1);
} else if (lua_isinteger(L, -1)) {
v = lua_tointeger(L, -1);
} else {
v = lua_tonumber(L, -1);
}
p->setter(obj, v);
} else if (p->type == SETTER_TYPE_COLOR) {
/* color */
lv_color_t color = luavgl_tocolor(L, -1);
p->setter(obj, color.full);
} else if (p->type == SETTER_TYPE_IMGSRC) {
/* img src */
p->setter_pointer(obj, (void *)luavgl_toimgsrc(L, -1));
} else if (p->type == SETTER_TYPE_STACK) {
p->setter_stack(obj, L);
} else if (p->type == SETTER_TYPE_POINTER) {
void *data = lua_touserdata(L, -1);
p->setter_pointer(obj, data);
} else {
debug("unsupported type: %d\n", p->type);
}
return 0;
}
return -1; /* property not found */
}
LUALIB_API void _lv_dummy_set(void *obj, lua_State *L) {}
static int luavgl_pcall_int(lua_State *L, int nargs, int nresult)
{
return luavgl_context(L)->pcall(L, nargs, nresult);
}
+169
View File
@@ -0,0 +1,169 @@
#include "luavgl.h"
#include "private.h"
static int luavgl_calendar_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_calendar_create);
}
static void _lv_calendar_set_today(void *obj, lua_State *L)
{
if (!lua_istable(L, -1)) {
luaL_argerror(L, -1, "expect date table.");
return;
}
uint32_t year, month, day;
lua_getfield(L, -1, "year");
year = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "month");
month = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "day");
day = lua_tointeger(L, -1);
lua_pop(L, 1);
lv_calendar_set_today_date(obj, year, month, day);
}
static void _lv_calendar_set_showed(void *obj, lua_State *L)
{
if (!lua_istable(L, -1)) {
luaL_argerror(L, -1, "expect date table.");
return;
}
uint32_t year, month;
lua_getfield(L, -1, "year");
year = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "month");
month = lua_tointeger(L, -1);
lua_pop(L, 1);
lv_calendar_set_showed_date(obj, year, month);
}
static const luavgl_value_setter_t calendar_property_table[] = {
{"today", SETTER_TYPE_STACK, {.setter_stack = _lv_calendar_set_today} },
{"showed", SETTER_TYPE_STACK, {.setter_stack = _lv_calendar_set_showed}},
};
LUALIB_API int luavgl_calendar_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, calendar_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_obj_set_property_kv(L, obj);
if (ret != 0) {
debug("unkown property for calendar.\n");
}
return ret;
}
static int luavgl_calendar_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_iterate(L, -1, luavgl_calendar_set_property_kv, obj);
return 0;
}
static inline int calendar_new_date(lua_State *L,
const lv_calendar_date_t *date)
{
lua_createtable(L, 0, 3);
lua_pushinteger(L, date->year);
lua_setfield(L, -2, "year");
lua_pushinteger(L, date->month);
lua_setfield(L, -2, "month");
lua_pushinteger(L, date->day);
lua_setfield(L, -2, "day");
return 1;
}
static int luavgl_calendar_get_today(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
const lv_calendar_date_t *date = lv_calendar_get_today_date(obj);
return calendar_new_date(L, date);
}
static int luavgl_calendar_get_showed(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
const lv_calendar_date_t *date = lv_calendar_get_showed_date(obj);
return calendar_new_date(L, date);
}
static int luavgl_calendar_get_pressed(lua_State *L)
{
lv_calendar_date_t date;
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_calendar_get_pressed_date(obj, &date);
return calendar_new_date(L, &date);
}
static int luavgl_calendar_get_btnm(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_obj_t *btm = lv_calendar_get_btnmatrix(obj);
lua_pushlightuserdata(L, btm);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
luavgl_add_lobj(L, btm)->lua_created = false;
}
return 1; /* obj userdata is already on stack */
}
static int luavgl_calendar_create_arrow(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_calendar_header_arrow_create);
}
static int luavgl_calendar_create_dropdown(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_calendar_header_dropdown_create);
}
static const luaL_Reg luavgl_calendar_methods[] = {
{"set", luavgl_calendar_set },
{"get_today", luavgl_calendar_get_today },
{"get_showed", luavgl_calendar_get_showed },
{"get_pressed", luavgl_calendar_get_pressed },
{"get_btnm", luavgl_calendar_get_btnm },
{"Arrow", luavgl_calendar_create_arrow },
{"Dropdown", luavgl_calendar_create_dropdown},
{NULL, NULL },
};
static void luavgl_calendar_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_calendar_class, "lv_calendar",
luavgl_calendar_methods);
lua_pop(L, 1);
}
+74
View File
@@ -0,0 +1,74 @@
#include "luavgl.h"
#include "private.h"
static int luavgl_checkbox_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_checkbox_create);
}
static void _lv_checkbox_set_txt(void *obj, lua_State *L)
{
if (!lua_isstring(L, -1)) {
luaL_argerror(L, -1, "only support string for text.");
return;
}
lv_checkbox_set_text(obj, lua_tostring(L, -1));
}
static const luavgl_value_setter_t checkbox_property_table[] = {
{"text", SETTER_TYPE_STACK, {.setter_stack = _lv_checkbox_set_txt}},
};
LUALIB_API int luavgl_checkbox_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, checkbox_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_obj_set_property_kv(L, obj);
if (ret != 0) {
debug("unkown property for checkbox.\n");
}
return ret;
}
static int luavgl_checkbox_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_iterate(L, -1, luavgl_checkbox_set_property_kv, obj);
return 0;
}
static int luavgl_checkbox_get_text(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushstring(L, lv_checkbox_get_text(obj));
return 1;
}
static const luaL_Reg luavgl_checkbox_methods[] = {
{"set", luavgl_checkbox_set },
{"get_text", luavgl_checkbox_get_text},
{NULL, NULL },
};
static void luavgl_checkbox_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_checkbox_class, "lv_checkbox",
luavgl_checkbox_methods);
lua_pop(L, 1);
}
+188
View File
@@ -0,0 +1,188 @@
#include "luavgl.h"
#include "private.h"
static int luavgl_dropdown_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_dropdown_create);
}
static void _lv_dropdown_set_text(void *obj, lua_State *L)
{
const char *str = lua_tostring(L, -1);
lv_dropdown_set_text(obj, str);
}
/* clang-format off */
static const luavgl_value_setter_t dropdown_property_table[] = {
{"text", SETTER_TYPE_STACK, {.setter_stack = _lv_dropdown_set_text}},
{"options", SETTER_TYPE_STACK, {.setter_stack = _lv_dummy_set}},
{"selected", 0, {.setter = (setter_int_t)lv_dropdown_set_selected}},
{"dir", 0, {.setter = (setter_int_t)lv_dropdown_set_dir}},
{"symbol", SETTER_TYPE_IMGSRC, {.setter_pointer = (setter_pointer_t)lv_dropdown_set_symbol}},
{"highlight", 0, {.setter = (setter_int_t)lv_dropdown_set_selected_highlight}},
};
/* clang-format on */
LUALIB_API int luavgl_dropdown_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, dropdown_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_obj_set_property_kv(L, obj);
if (ret != 0) {
debug("unkown property for dropdown.\n");
}
return ret;
}
static int luavgl_dropdown_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
/* set options firstly, otherwise set selected may fail */
lua_getfield(L, -1, "options");
if (lua_type(L, -1) == LUA_TSTRING) {
lv_dropdown_set_options(obj, lua_tostring(L, -1));
}
lua_pop(L, 1);
luavgl_iterate(L, -1, luavgl_dropdown_set_property_kv, obj);
return 0;
}
static int luavgl_dropdown_get(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (lua_type(L, 2) != LUA_TSTRING) {
return luaL_argerror(L, 2, "expect string");
}
const char *key = lua_tostring(L, 2);
if (strcmp(key, "list") == 0) {
lv_obj_t *list = lv_dropdown_get_list(obj);
lua_pushlightuserdata(L, list);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isnoneornil(L, -1)) {
lua_pop(L, 1);
luavgl_add_lobj(L, list)->lua_created = false;
}
return 1;
}
if (strcmp(key, "text") == 0) {
lua_pushstring(L, lv_dropdown_get_text(obj));
return 1;
}
if (strcmp(key, "options") == 0) {
lua_pushstring(L, lv_dropdown_get_options(obj));
return 1;
}
if (strcmp(key, "selected") == 0) {
lua_pushinteger(L, lv_dropdown_get_selected(obj));
return 1;
}
if (strcmp(key, "option_cnt") == 0) {
lua_pushinteger(L, lv_dropdown_get_option_cnt(obj));
return 1;
}
if (strcmp(key, "selected_str") == 0) {
char buf[64];
lv_dropdown_get_selected_str(obj, buf, sizeof(buf));
lua_pushstring(L, buf);
return 1;
}
if (strcmp(key, "option_index") == 0) {
const char *option = lua_tostring(L, 3);
lua_pushinteger(L, lv_dropdown_get_option_index(obj, option));
return 1;
}
if (strcmp(key, "symbol") == 0) {
lua_pushlightuserdata(L, (void *)lv_dropdown_get_symbol(obj));
return 1;
}
if (strcmp(key, "dir") == 0) {
lua_pushinteger(L, lv_dropdown_get_dir(obj));
return 1;
}
return 0;
}
static int luavgl_dropdown_open(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_dropdown_open(obj);
return 0;
}
static int luavgl_dropdown_close(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_dropdown_close(obj);
return 0;
}
static int luavgl_dropdown_is_open(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushboolean(L, lv_dropdown_is_open(obj));
return 1;
}
static int luavgl_dropdown_add_option(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
const char *str = lua_tostring(L, 2);
uint32_t pos = lua_tointeger(L, 3);
lv_dropdown_add_option(obj, str, pos);
return 0;
}
static int luavgl_dropdown_clear_option(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_dropdown_clear_options(obj);
return 0;
}
static const luaL_Reg luavgl_dropdown_methods[] = {
{"set", luavgl_dropdown_set },
{"get", luavgl_dropdown_get },
{"open", luavgl_dropdown_open },
{"close", luavgl_dropdown_close },
{"is_open", luavgl_dropdown_is_open },
{"add_option", luavgl_dropdown_add_option },
{"clear_option", luavgl_dropdown_clear_option},
{NULL, NULL },
};
static void luavgl_dropdown_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_dropdown_class, "lv_dropdown",
luavgl_dropdown_methods);
lua_pop(L, 1);
}
+196
View File
@@ -0,0 +1,196 @@
#include "luavgl.h"
#include "private.h"
static int luavgl_img_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_img_create);
}
static void _lv_img_set_pivot(void *obj, lua_State *L)
{
if (!lua_istable(L, -1)) {
luaL_argerror(L, -1, "should be table.");
debug("para should be table.");
return;
}
lua_getfield(L, -1, "x");
lv_coord_t x = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "y");
lv_coord_t y = lua_tointeger(L, -1);
lua_pop(L, 1);
lv_img_set_pivot(obj, x, y);
}
static const luavgl_value_setter_t img_property_table[] = {
{"src",
SETTER_TYPE_IMGSRC, {.setter_pointer = (setter_pointer_t)lv_img_set_src}},
{"offset_x", 0, {.setter = (setter_int_t)lv_img_set_offset_x} },
{"offset_y", 0, {.setter = (setter_int_t)lv_img_set_offset_y} },
{"angle", 0, {.setter = (setter_int_t)lv_img_set_angle} },
{"zoom", 0, {.setter = (setter_int_t)lv_img_set_zoom} },
{"antialias", 0, {.setter = (setter_int_t)lv_img_set_antialias} },
{"pivot", SETTER_TYPE_STACK, {.setter_stack = _lv_img_set_pivot} },
};
LUALIB_API int luavgl_img_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, img_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_obj_set_property_kv(L, obj);
if (ret != 0) {
debug("unkown property for image.\n");
}
return ret;
}
static int luavgl_img_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
/* lvgl requires img src should be set firstly */
lua_getfield(L, -1, "src");
if (!lua_isnoneornil(L, -1)) {
const char *src = NULL;
if (lua_isuserdata(L, -1)) {
src = lua_touserdata(L, -1);
debug("set img src to user data: %p\n", src);
} else {
src = lua_tostring(L, -1);
}
lv_img_set_src(obj, src);
}
lua_pop(L, 1);
luavgl_iterate(L, -1, luavgl_img_set_property_kv, obj);
return 0;
}
/**
* img.set_src(img, "path")
*/
static int luavgl_img_set_src(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
const char *src = luavgl_toimgsrc(L, 2);
if (src != NULL) {
lv_img_set_src(obj, src);
}
return 0;
}
/**
* img:set_offset({x=10})
* img:set_offset({x=10})
* img:set_offset({x=10, y=100})
*/
static int luavgl_img_set_offset(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_argerror(L, -1, "should be table {x=0,y=0,anim=true}");
}
lv_coord_t v;
lua_getfield(L, -1, "x");
if (!lua_isnil(L, -1)) {
v = lua_tointeger(L, -1);
lua_pop(L, 1);
lv_img_set_offset_x(obj, v);
}
lua_getfield(L, -1, "y");
if (!lua_isnil(L, -1)) {
v = lua_tointeger(L, -1);
lua_pop(L, 1);
lv_img_set_offset_y(obj, v);
}
return 0;
}
/**
* img:set_pivot({x=10, y=100})
*/
static int luavgl_img_set_pivot(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_argerror(L, -1, "should be table {x=0,y=0,anim=true}");
}
lv_coord_t x = 0, y = 0;
lua_getfield(L, -1, "x");
x = lua_tointeger(L, -1);
lua_getfield(L, -1, "y");
y = lua_tointeger(L, -1);
lv_img_set_pivot(obj, x, y);
return 0;
}
/**
* return image size w, h
* img:get_img_size() -- get size of this image
* img:get_img_size("src") -- get size of img "src"
*/
static int luavgl_get_img_size(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
const void *src = NULL;
if (lua_isnoneornil(L, 2)) {
src = lv_img_get_src(obj);
} else {
src = luavgl_toimgsrc(L, 2);
}
lv_img_header_t header;
if (src == NULL || lv_img_decoder_get_info(src, &header) != LV_RES_OK) {
lua_pushnil(L);
lua_pushnil(L);
} else {
lua_pushinteger(L, header.w);
lua_pushinteger(L, header.h);
}
return 2;
}
static const luaL_Reg luavgl_img_methods[] = {
{"set", luavgl_img_set },
{"set_src", luavgl_img_set_src },
{"set_offset", luavgl_img_set_offset},
{"set_pivot", luavgl_img_set_pivot },
{"get_img_size", luavgl_get_img_size },
{NULL, NULL },
};
static void luavgl_img_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_img_class, "lv_img", luavgl_img_methods);
lua_pop(L, 1);
}
+76
View File
@@ -0,0 +1,76 @@
#include "luavgl.h"
#include "private.h"
static int luavgl_keyboard_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_keyboard_create);
}
static void _lv_keyboard_set_textarea(void *obj, lua_State *L)
{
lv_obj_t *ta = luavgl_to_obj(L, -1);
if (ta->class_p != &lv_textarea_class) {
luaL_argerror(L, -1, "expect textarea obj");
return;
}
lv_keyboard_set_textarea(obj, ta);
}
/* clang-format off */
static const luavgl_value_setter_t keyboard_property_table[] = {
{"textarea", SETTER_TYPE_STACK, {.setter_stack = _lv_keyboard_set_textarea}},
{"mode", SETTER_TYPE_INT, {.setter = (setter_int_t)lv_keyboard_set_mode}},
{"popovers", SETTER_TYPE_INT, {.setter = (setter_int_t)lv_keyboard_set_popovers}},
};
/* clang-format on */
LUALIB_API int luavgl_keyboard_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, keyboard_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_obj_set_property_kv(L, obj);
if (ret != 0) {
debug("unkown property for keyboard.\n");
}
return ret;
}
static int luavgl_keyboard_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_iterate(L, -1, luavgl_keyboard_set_property_kv, obj);
return 0;
}
static const luaL_Reg luavgl_keyboard_methods[] = {
{"set", luavgl_keyboard_set},
{NULL, NULL },
};
static void luavgl_keyboard_init(lua_State *L)
{
static const luaL_Reg btm_methods[] = {
{NULL, NULL},
};
luavgl_obj_newmetatable(L, &lv_btnmatrix_class, "lv_btnm", btm_methods);
lua_pop(L, 1);
luavgl_obj_newmetatable(L, &lv_keyboard_class, "lv_keyboard",
luavgl_keyboard_methods);
lua_pop(L, 1);
}
+155
View File
@@ -0,0 +1,155 @@
#include "luavgl.h"
#include "private.h"
static int luavgl_label_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_label_create);
}
static void _lv_label_set_txt(void *obj, lua_State *L)
{
if (!lua_isstring(L, -1)) {
luaL_argerror(L, -1, "only support string for text.");
return;
}
lv_label_set_text(obj, lua_tostring(L, -1));
}
static const luavgl_value_setter_t label_property_table[] = {
{"text", SETTER_TYPE_STACK, {.setter_stack = _lv_label_set_txt} },
{"long_mode", 0, {.setter = (setter_int_t)lv_label_set_long_mode} },
{"recolor", 0, {.setter = (setter_int_t)lv_label_set_recolor} },
#if LVGL_VERSION_MAJOR == 9
{"text_selection_start",
0, {.setter = (setter_int_t)lv_label_set_text_selection_start}},
{"text_selection_end",
0, {.setter = (setter_int_t)lv_label_set_text_selection_end} },
#else
{"text_selection_start",
0,
{.setter = (setter_int_t)lv_label_set_text_sel_start}},
{"text_selection_end",
0,
{.setter = (setter_int_t)lv_label_set_text_sel_end}},
#endif
};
LUALIB_API int luavgl_label_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, label_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_obj_set_property_kv(L, obj);
if (ret != 0) {
debug("unkown property for label.\n");
}
return ret;
}
static int luavgl_label_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_iterate(L, -1, luavgl_label_set_property_kv, obj);
return 0;
}
static int luavgl_label_get_text(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushstring(L, lv_label_get_text(obj));
return 1;
}
static int luavgl_label_get_long_mode(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushinteger(L, lv_label_get_long_mode(obj));
return 1;
}
static int luavgl_label_get_recolor(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushinteger(L, lv_label_get_recolor(obj));
return 1;
}
static int luavgl_label_ins_text(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
uint32_t pos = luavgl_tointeger(L, 2);
const char *txt = lua_tostring(L, 3);
lv_label_ins_text(obj, pos, txt);
return 0;
}
static int luavgl_label_cut_text(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
uint32_t pos = luavgl_tointeger(L, 2);
uint32_t cnt = luavgl_tointeger(L, 3);
lv_label_cut_text(obj, pos, cnt);
return 0;
}
/* demo purpose, there is no need to use set_text_static */
static int luavgl_label_set_text_static(lua_State *L)
{
const char *str = lua_tostring(L, 2);
luavgl_obj_t *lobj = luavgl_to_lobj(L, 1);
if (lobj->obj == NULL) {
return luaL_error(L, "obj null.");
}
luavgl_obj_getuserdatauv(L, 1);
/* uservalue is on top */
lua_pushvalue(L, 2);
lua_setfield(L, -2, "text_static");
lv_label_set_text_static(lobj->obj, str);
return 0;
}
static int luavgl_label_tostring(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushfstring(L, "lv_label:%p, text: %s", obj, lv_label_get_text(obj));
return 1;
}
static const luaL_Reg luavgl_label_methods[] = {
{"set", luavgl_label_set },
{"set_text_static", luavgl_label_set_text_static},
{"get_text", luavgl_label_get_text },
{"get_long_mode", luavgl_label_get_long_mode },
{"get_recolor", luavgl_label_get_recolor },
{"ins_text", luavgl_label_ins_text },
{"cut_text", luavgl_label_cut_text },
{NULL, NULL },
};
static void luavgl_label_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_label_class, "lv_label", luavgl_label_methods);
lua_pushcfunction(L, luavgl_label_tostring);
lua_setfield(L, -2, "__tostring");
lua_pop(L, 1);
}
+91
View File
@@ -0,0 +1,91 @@
#include "luavgl.h"
#include "private.h"
static int luavgl_led_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_led_create);
}
/* clang-format off */
static const luavgl_value_setter_t led_property_table[] = {
{"color", SETTER_TYPE_COLOR, {.setter = (setter_int_t)lv_led_set_color}},
{"brightness", 0, {.setter = (setter_int_t)lv_led_set_brightness}},
};
/* clang-format on */
LUALIB_API int luavgl_led_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, led_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_obj_set_property_kv(L, obj);
if (ret != 0) {
debug("unkown property for led.\n");
}
return ret;
}
static int luavgl_led_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_iterate(L, -1, luavgl_led_set_property_kv, obj);
return 0;
}
static int luavgl_led_on(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_led_on(obj);
return 0;
}
static int luavgl_led_off(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_led_off(obj);
return 0;
}
static int luavgl_led_toggle(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_led_toggle(obj);
return 0;
}
static int luavgl_led_get_brightness(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushinteger(L, lv_led_get_brightness(obj));
return 1;
}
static const luaL_Reg luavgl_led_methods[] = {
{"set", luavgl_led_set },
{"on", luavgl_led_on },
{"off", luavgl_led_off },
{"toggle", luavgl_led_toggle },
{"get_brightness", luavgl_led_get_brightness},
{NULL, NULL },
};
static void luavgl_led_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_led_class, "lv_led", luavgl_led_methods);
lua_pop(L, 1);
}
+89
View File
@@ -0,0 +1,89 @@
#include "luavgl.h"
#include "private.h"
static int luavgl_list_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_list_create);
}
/* clang-format off */
static const luavgl_value_setter_t list_property_table[] = {
{"dummy", SETTER_TYPE_STACK, {.setter_stack = _lv_dummy_set}},
};
/* clang-format on */
LUALIB_API int luavgl_list_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, list_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_obj_set_property_kv(L, obj);
if (ret != 0) {
debug("unkown property for list.\n");
}
return ret;
}
static int luavgl_list_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_iterate(L, -1, luavgl_list_set_property_kv, obj);
return 0;
}
static int luavgl_list_add_text(lua_State *L)
{
lv_obj_t *list = luavgl_to_obj(L, 1);
const char *str = lua_tostring(L, 2);
lv_obj_t *obj = lv_list_add_text(list, str);
luavgl_add_lobj(L, obj)->lua_created = true;
return 1;
}
static int luavgl_list_add_btn(lua_State *L)
{
lv_obj_t *list = luavgl_to_obj(L, 1);
const void *icon = luavgl_toimgsrc(L, 2);
const char *str = lua_tostring(L, 3);
lv_obj_t *obj = lv_list_add_btn(list, icon, str);
luavgl_add_lobj(L, obj)->lua_created = true;
return 1;
}
static int luavgl_get_btn_text(lua_State *L)
{
lv_obj_t *list = luavgl_to_obj(L, 1);
lv_obj_t *btn = luavgl_to_obj(L, 2);
lua_pushstring(L, lv_list_get_btn_text(list, btn));
return 1;
}
static const luaL_Reg luavgl_list_methods[] = {
{"set", luavgl_list_set },
{"add_text", luavgl_list_add_text},
{"add_btn", luavgl_list_add_btn },
{"get_btn_text", luavgl_get_btn_text },
{NULL, NULL },
};
static void luavgl_list_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_list_class, "lv_list", luavgl_list_methods);
lua_pop(L, 1);
}
+136
View File
@@ -0,0 +1,136 @@
#include "luavgl.h"
#include "private.h"
static int luavgl_roller_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_roller_create);
}
static void _lv_roller_set_options(void *obj, lua_State *L)
{
int type = lua_type(L, -1);
if (type == LUA_TSTRING) {
lv_roller_set_options(obj, lua_tostring(L, -1), 0);
} else if (type == LUA_TTABLE) {
lua_getfield(L, -1, "options");
if (!lua_isstring(L, -1)) {
luaL_error(L, "expect string.");
return;
}
const char *options = lua_tostring(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "mode");
lv_roller_mode_t mode = lua_tointeger(L, -1);
lua_pop(L, 1);
lv_roller_set_options(obj, options, mode);
return;
}
luaL_error(L, "expect string or table.");
}
static void _lv_roller_set_selected(void *obj, lua_State *L)
{
int type = lua_type(L, -1);
uint16_t selected;
int anim = 0;
if (type == LUA_TTABLE) {
lua_getfield(L, -1, "selected");
selected = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "anim");
anim = luavgl_tointeger(L, -1);
lua_pop(L, 1);
} else {
selected = lua_tointeger(L, -1);
}
lv_roller_set_selected(obj, selected, anim);
}
static const luavgl_value_setter_t roller_property_table[] = {
{"options", SETTER_TYPE_STACK, {.setter_stack = _lv_roller_set_options} },
{"selected", SETTER_TYPE_STACK, {.setter_stack = _lv_roller_set_selected} },
{"visible_cnt",
0, {.setter = (setter_int_t)lv_roller_set_visible_row_count}},
};
LUALIB_API int luavgl_roller_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, roller_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_obj_set_property_kv(L, obj);
if (ret != 0) {
debug("unkown property for roller.\n");
}
return ret;
}
static int luavgl_roller_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_iterate(L, -1, luavgl_roller_set_property_kv, obj);
return 0;
}
static int luavgl_roller_get_options(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushstring(L, lv_roller_get_options(obj));
return 1;
}
static int luavgl_roller_get_selected(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushinteger(L, lv_roller_get_selected(obj));
return 1;
}
static int luavgl_roller_get_selected_str(lua_State *L)
{
char buf[64];
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_roller_get_selected_str(obj, buf, sizeof(buf));
lua_pushstring(L, buf);
return 1;
}
static int luavgl_roller_get_options_cnt(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushinteger(L, lv_roller_get_option_cnt(obj));
return 1;
}
static const luaL_Reg luavgl_roller_methods[] = {
{"set", luavgl_roller_set },
{"get_options", luavgl_roller_get_options },
{"get_selected", luavgl_roller_get_selected },
{"get_selected_str", luavgl_roller_get_selected_str},
{"get_options_cnt", luavgl_roller_get_options_cnt },
{NULL, NULL },
};
static void luavgl_roller_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_roller_class, "lv_roller", luavgl_roller_methods);
lua_pop(L, 1);
}
+117
View File
@@ -0,0 +1,117 @@
#include "luavgl.h"
#include "private.h"
static int luavgl_textarea_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_textarea_create);
}
static void _lv_textarea_set_txt(void *obj, lua_State *L)
{
if (!lua_isstring(L, -1)) {
luaL_argerror(L, -1, "expect string");
return;
}
lv_textarea_set_text(obj, lua_tostring(L, -1));
}
static void _lv_textarea_set_placeholder_txt(void *obj, lua_State *L)
{
if (!lua_isstring(L, -1)) {
luaL_argerror(L, -1, "expect string");
return;
}
lv_textarea_set_placeholder_text(obj, lua_tostring(L, -1));
}
static void _lv_textarea_set_password_bullet(void *obj, lua_State *L)
{
if (!lua_isstring(L, -1)) {
luaL_argerror(L, -1, "expect string");
return;
}
lv_textarea_set_password_bullet(obj, lua_tostring(L, -1));
}
static void _lv_textarea_set_accepted_chars(void *obj, lua_State *L)
{
if (!lua_isstring(L, -1)) {
luaL_argerror(L, -1, "expect string");
return;
}
lv_textarea_set_accepted_chars(obj, lua_tostring(L, -1));
}
/* clang-format off */
static const luavgl_value_setter_t textarea_property_table[] = {
{"text", SETTER_TYPE_STACK, {.setter_stack = _lv_textarea_set_txt}},
{"placeholder", SETTER_TYPE_STACK, {.setter_stack = _lv_textarea_set_placeholder_txt}},
{"cursor", SETTER_TYPE_INT, {.setter = (setter_int_t)lv_textarea_set_cursor_pos}},
{"password_mode", SETTER_TYPE_INT, {.setter = (setter_int_t)lv_textarea_set_password_mode}},
{"one_line", SETTER_TYPE_INT, {.setter = (setter_int_t)lv_textarea_set_one_line}},
{"password_bullet", SETTER_TYPE_STACK, {.setter_stack = _lv_textarea_set_password_bullet}},
{"accepted_chars", SETTER_TYPE_STACK, {.setter_stack = _lv_textarea_set_accepted_chars}},
{"max_length", SETTER_TYPE_INT, {.setter = (setter_int_t)lv_textarea_set_max_length}},
{"password_show_time", SETTER_TYPE_INT, {.setter = (setter_int_t)lv_textarea_set_password_show_time}},
};
/* clang-format on */
LUALIB_API int luavgl_textarea_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, textarea_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_obj_set_property_kv(L, obj);
if (ret != 0) {
debug("unkown property for textarea: %s\n", lua_tostring(L, -2));
}
return -1;
}
static int luavgl_textarea_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_iterate(L, -1, luavgl_textarea_set_property_kv, obj);
return 0;
}
/**
* obj:get_text()
*/
static int luavgl_textarea_get_text(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lua_pushstring(L, lv_textarea_get_text(obj));
return 1;
}
static const luaL_Reg luavgl_textarea_methods[] = {
{"set", luavgl_textarea_set },
{"get_text", luavgl_textarea_get_text},
{NULL, NULL },
};
static void luavgl_textarea_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_textarea_class, "lv_textarea",
luavgl_textarea_methods);
lua_pop(L, 1);
}
+133
View File
@@ -0,0 +1,133 @@
#include "luavgl.h"
#include "private.h"
#if LV_USE_CALENDAR
#include "calendar.c"
#endif
#if LV_USE_CHECKBOX
#include "checkbox.c"
#endif
#if LV_USE_DROPDOWN
#include "dropdown.c"
#endif
#if LV_USE_IMG
#include "img.c"
#endif
#if LV_USE_KEYBOARD
#include "keyboard.c"
#endif
#if LV_USE_LABEL
#include "label.c"
#endif
#if LV_USE_LED
#include "led.c"
#endif
#if LV_USE_LIST
#include "list.c"
#endif
#if LV_USE_ROLLER
#include "roller.c"
#endif
#if LV_USE_TEXTAREA
#include "textarea.c"
#endif
static int luavgl_obj_create(lua_State *L);
static const luaL_Reg widget_create_methods[] = {
{"Object", luavgl_obj_create },
#if LV_USE_CALENDAR
{"Calendar", luavgl_calendar_create},
#endif
#if LV_USE_CHECKBOX
{"Checkbox", luavgl_checkbox_create},
#endif
#if LV_USE_DROPDOWN
{"Dropdown", luavgl_dropdown_create},
#endif
#if LV_USE_IMG
{"Image", luavgl_img_create },
#endif
#if LV_USE_KEYBOARD
{"Keyboard", luavgl_keyboard_create},
#endif
#if LV_USE_LABEL
{"Label", luavgl_label_create },
#endif
#if LV_USE_LED
{"Led", luavgl_led_create },
#endif
#if LV_USE_LIST
{"List", luavgl_list_create },
#endif
#if LV_USE_ROLLER
{"Roller", luavgl_roller_create },
#endif
#if LV_USE_TEXTAREA
{"Textarea", luavgl_textarea_create},
#endif
{NULL, NULL }
};
static void luavgl_widgets_init(lua_State *L)
{
#if LV_USE_IMG
luavgl_img_init(L);
#endif
#if LV_USE_LABEL
luavgl_label_init(L);
#endif
#if LV_USE_LED
luavgl_led_init(L);
#endif
#if LV_USE_LIST
luavgl_list_init(L);
#endif
#if LV_USE_TEXTAREA
luavgl_textarea_init(L);
#endif
#if LV_USE_KEYBOARD
luavgl_keyboard_init(L);
#endif
#if LV_USE_CHECKBOX
luavgl_checkbox_init(L);
#endif
#if LV_USE_CALENDAR
luavgl_calendar_init(L);
#endif
#if LV_USE_ROLLER
luavgl_roller_init(L);
#endif
#if LV_USE_DROPDOWN
luavgl_dropdown_init(L);
#endif
}