Convert the main menu screen to lua lol
@@ -0,0 +1,6 @@
|
||||
BasedOnStyle: llvm
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterFunction: true
|
||||
AlignArrayOfStructures: Left
|
||||
SeparateDefinitionBlocks: Always
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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")
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
@@ -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
|
||||
}
|
||||
@@ -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")
|
||||
@@ -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)
|
||||
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 323 B |
|
After Width: | Height: | Size: 253 B |
|
After Width: | Height: | Size: 250 B |
|
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.8:90 ~ -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)
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 536 B |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
@@ -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
|
||||
@@ -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,
|
||||
})
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
@@ -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()
|
||||
@@ -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})
|
||||
@@ -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"*/
|
||||
@@ -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"*/
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
@@ -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_ */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
---
|
||||
@@ -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 */
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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.");
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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 */
|
||||
}
|
||||
@@ -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 */
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||