Convert the main menu screen to lua lol

This commit is contained in:
jacqueline
2023-11-12 19:14:09 +11:00
parent 8471046a95
commit 8a0a167adb
206 changed files with 42303 additions and 183 deletions
+113
View File
@@ -0,0 +1,113 @@
#include <lauxlib.h>
#include <lua.h>
#include <lvgl.h>
#include <stdlib.h>
#include <luavgl.h>
#include "lv_analog_time.h"
static int luavgl_analog_time_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_analog_time_create);
}
static void _lv_analog_time_set_hands(void *obj, lua_State *L)
{
if (!lua_istable(L, -1)) {
luaL_argerror(L, -1, "expect date table.");
return;
}
const void *hour, *minute, *second;
lua_getfield(L, -1, "hour");
hour = luavgl_toimgsrc(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "minute");
minute = luavgl_toimgsrc(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "second");
second = luavgl_toimgsrc(L, -1);
lua_pop(L, 1);
lv_analog_time_set_hands(obj, hour, minute, second);
}
/* clang-format off */
static const luavgl_value_setter_t analog_time_property_table[] = {
{"hands", SETTER_TYPE_STACK, {.setter_stack = _lv_analog_time_set_hands}},
{"period", SETTER_TYPE_INT, {.setter = (setter_int_t)lv_analog_time_set_period}},
};
/* clang-format on */
static int luavgl_analog_time_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, analog_time_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_obj_set_property_kv(L, obj);
if (ret != 0) {
printf("unkown property for analog_time: %s\n", lua_tostring(L, -2));
}
return -1;
}
static int luavgl_analog_time_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_iterate(L, -1, luavgl_analog_time_set_property_kv, obj);
return 0;
}
static int luavgl_analog_time_pause(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_analog_time_pause(obj);
return 0;
}
static int luavgl_analog_time_resume(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
lv_analog_time_resume(obj);
return 0;
}
static const luaL_Reg luavgl_analog_time_methods[] = {
{"set", luavgl_analog_time_set },
{"pause", luavgl_analog_time_pause },
{"resume", luavgl_analog_time_resume},
{NULL, NULL },
};
void luavgl_analog_time_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_analog_time_class, "lv_analog_time",
luavgl_analog_time_methods);
lua_pop(L, 1);
luaL_getmetatable(L, "widgets");
lua_getfield(L, -1, "__index");
lua_pushcfunction(L, luavgl_analog_time_create);
lua_setfield(L, -2, "AnalogTime");
lua_pop(L, 2);
}
+69
View File
@@ -0,0 +1,69 @@
#include <lauxlib.h>
#include <lua.h>
#include <lvgl.h>
#include <stdlib.h>
#include <luavgl.h>
static int luavgl_extension_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_obj_create);
}
/* clang-format off */
static const luavgl_value_setter_t extension_property_table[] = {
{"dummy", SETTER_TYPE_STACK, {.setter_stack = _lv_dummy_set}},
};
/* clang-format on */
static int luavgl_extension_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, extension_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_obj_set_property_kv(L, obj);
if (ret != 0) {
printf("unkown property for extension.\n");
}
return ret;
}
static int luavgl_extension_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_iterate(L, -1, luavgl_extension_set_property_kv, obj);
return 0;
}
static const luaL_Reg luavgl_extension_methods[] = {
{"set", luavgl_extension_set},
{NULL, NULL},
};
void luavgl_extension_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_btn_class, "lv_extension",
luavgl_extension_methods);
lua_pop(L, 1);
luaL_getmetatable(L, "widgets");
lua_getfield(L, -1, "__index");
lua_pushcfunction(L, luavgl_extension_create);
lua_setfield(L, -2, "Extension");
lua_pop(L, 2);
}
@@ -0,0 +1,253 @@
/*********************
* INCLUDES
*********************/
#include "lv_analog_time.h"
#include "lv_pointer.h"
#include <time.h>
#if LV_USE_ANALOG_TIME
/*********************
* DEFINES
*********************/
#define MY_CLASS &lv_analog_time_class
#define UNIT_ONE_SECOND (1000)
#define UNIT_ONE_MINUTE (60 * UNIT_ONE_SECOND)
#define UNIT_ONE_HOUR (60 * UNIT_ONE_MINUTE)
#define UNIT_ONE_DAY (24 * UNIT_ONE_HOUR)
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_analog_time_constructor(const lv_obj_class_t* class_p,
lv_obj_t* obj);
static void lv_analog_time_destructor(const lv_obj_class_t* class_p,
lv_obj_t* obj);
static void update_time(lv_obj_t* obj);
static void timer_cb(lv_timer_t* timer);
static lv_obj_t* create_hand(lv_obj_t* obj, const char* img);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_analog_time_class = {
.constructor_cb = lv_analog_time_constructor,
.destructor_cb = lv_analog_time_destructor,
.instance_size = sizeof(lv_analog_time_t),
.base_class = &lv_obj_class,
};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_obj_t* lv_analog_time_create(lv_obj_t* parent)
{
lv_obj_t* obj = lv_obj_class_create_obj(MY_CLASS, parent);
lv_obj_class_init_obj(obj);
return obj;
}
void lv_analog_time_set_hands(lv_obj_t* obj, const void* hour,
const void* minute, const void* second)
{
lv_analog_time_t* analog = (lv_analog_time_t*)obj;
uint32_t period = UNIT_ONE_MINUTE; /* default */
/* remove hand if it's null */
if (analog->second) {
lv_obj_del(analog->second);
analog->second = NULL;
}
if (analog->minute) {
lv_obj_del(analog->minute);
analog->minute = NULL;
}
if (analog->hour) {
lv_obj_del(analog->hour);
analog->hour = NULL;
}
/* create hand if not null */
if (hour) {
analog->hour = create_hand(obj, hour);
/* for hour, we use minute as unit*/
lv_pointer_set_range(analog->hour, 0, 24 * 60, 0, 3600 * 2);
/* update period should be faster than 1minute(default) */
}
if (minute) {
analog->minute = create_hand(obj, minute);
/* for minute, update per second */
lv_pointer_set_range(analog->minute, 0, 60 * 60, 0, 3600);
/* update period should be faster than 1second */
if (period > 1 * UNIT_ONE_SECOND) {
period = UNIT_ONE_SECOND;
}
}
if (second) {
analog->second = create_hand(obj, second);
/* update per second */
lv_pointer_set_range(analog->second, 0, 60 * UNIT_ONE_SECOND, 0, 3600);
/* update period should be faster than 1second */
if (period > 1 * UNIT_ONE_SECOND) {
period = UNIT_ONE_SECOND;
}
}
if (period < analog->period)
analog->period = period;
if (analog->hour || analog->minute || analog->second) {
lv_timer_resume(analog->timer);
} else {
/* no more needed */
lv_timer_pause(analog->timer);
}
update_time(obj);
}
void lv_analog_time_pause(lv_obj_t* obj)
{
lv_analog_time_t* analog = (lv_analog_time_t*)obj;
lv_timer_pause(analog->timer);
}
void lv_analog_time_resume(lv_obj_t* obj)
{
lv_analog_time_t* analog = (lv_analog_time_t*)obj;
lv_timer_resume(analog->timer);
update_time(obj);
}
void lv_analog_time_set_period(lv_obj_t* obj, uint32_t period)
{
lv_analog_time_t* analog = (lv_analog_time_t*)obj;
analog->period = period;
lv_timer_set_period(analog->timer, period);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void lv_analog_time_constructor(const lv_obj_class_t* class_p,
lv_obj_t* obj)
{
LV_UNUSED(class_p);
LV_TRACE_OBJ_CREATE("begin");
lv_analog_time_t* analog = (lv_analog_time_t*)obj;
analog->period = 60 * 60 * 1000; /* default to 1Hour = 60min*60sec*1000ms*/
lv_obj_add_flag(lv_obj_get_parent(obj), LV_OBJ_FLAG_OVERFLOW_VISIBLE);
/* hands pivot is place to 0, 0 */
lv_obj_remove_style_all(obj);
lv_obj_set_size(obj, 0, 0);
analog->timer = lv_timer_create(timer_cb, UNIT_ONE_MINUTE, obj);
lv_timer_pause(analog->timer);
LV_TRACE_OBJ_CREATE("finished");
}
static void lv_analog_time_destructor(const lv_obj_class_t* class_p,
lv_obj_t* obj)
{
lv_analog_time_t* analog = (lv_analog_time_t*)obj;
lv_timer_del(analog->timer);
}
static lv_obj_t* create_hand(lv_obj_t* obj, const char* img)
{
lv_obj_t* hand;
hand = lv_pointer_create(obj);
lv_img_set_src(hand, img);
lv_point_t pivot;
lv_img_get_pivot(hand, &pivot);
/* we position the hand using image's center */
lv_obj_set_pos(hand, -pivot.x, -pivot.y);
return hand;
}
static void update_time(lv_obj_t* obj)
{
int value;
struct timespec ts;
struct tm* time;
int ret;
ret = clock_gettime(CLOCK_REALTIME, &ts);
if (ret != 0) {
LV_LOG_ERROR("get real time failed");
return;
}
time = localtime(&ts.tv_sec);
if (time == NULL) {
LV_LOG_ERROR("get local time failed");
return;
}
lv_analog_time_t* analog = (lv_analog_time_t*)obj;
value = time->tm_sec * 1000;
if (analog->period < UNIT_ONE_SECOND) {
/* sub-second update mode */
value += ts.tv_nsec / 1000000; /* add ms part */
}
if (analog->second)
lv_pointer_set_value(analog->second, value);
if (analog->minute)
lv_pointer_set_value(analog->minute, time->tm_min * 60 + time->tm_sec);
if (analog->hour)
lv_pointer_set_value(analog->hour, time->tm_hour * 60 + time->tm_min);
}
static void timer_cb(lv_timer_t* t)
{
/* timeup */
update_time(t->user_data);
}
/* examples */
#if 0
void lv_analog_time_example(void)
{
lv_obj_t* scr = lv_scr_act();
lv_obj_t* analog = lv_analog_time_create(scr);
lv_obj_center(analog);
lv_analog_time_set_hands(analog, "/data/hand-second.png", "/data/hand-second.png", "/data/hand-second.png");
lv_analog_time_set_period(analog, 60);
}
#endif
#endif
@@ -0,0 +1,64 @@
#ifndef LV_WIDGETS_ANALOG_TIME_H_
#define LV_WIDGETS_ANALOG_TIME_H_
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <lvgl.h>
#if LV_USE_ANALOG_TIME
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_obj_t obj;
lv_obj_t* hour;
lv_obj_t* minute;
lv_obj_t* second;
uint32_t period;
lv_timer_t* timer;
} lv_analog_time_t;
extern const lv_obj_class_t lv_analog_time_class;
/**********************
* GLOBAL PROTOTYPES
**********************/
lv_obj_t* lv_analog_time_create(lv_obj_t* parent);
/**
* Set images for hands of hour, minute and second.
* If specified hands image is NULL, then it's deleted.
*
* @note for simplicity, image pivot is set to image center.
*/
void lv_analog_time_set_hands(lv_obj_t* obj, const void* hour,
const void* minute, const void* second);
void lv_analog_time_pause(lv_obj_t* obj);
void lv_analog_time_resume(lv_obj_t* obj);
void lv_analog_time_set_period(lv_obj_t* obj, uint32_t period);
/**********************
* MACROS
**********************/
#endif /* */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* LV_WIDGETS_ANALOG_TIME_H_ */
+138
View File
@@ -0,0 +1,138 @@
/*********************
* INCLUDES
*********************/
#include "lv_pointer.h"
#if LV_USE_POINTER
/*********************
* DEFINES
*********************/
#define MY_CLASS &lv_pointer_class
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_pointer_constructor(const lv_obj_class_t* class_p,
lv_obj_t* obj);
static void angle_update(lv_obj_t* obj);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_pointer_class = {
.constructor_cb = lv_pointer_constructor,
.instance_size = sizeof(lv_pointer_t),
.base_class = &lv_img_class,
};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_obj_t* lv_pointer_create(lv_obj_t* parent)
{
lv_obj_t* obj = lv_obj_class_create_obj(MY_CLASS, parent);
lv_obj_class_init_obj(obj);
/* pointer can rotate out of parent's area. */
lv_obj_add_flag(parent, LV_OBJ_FLAG_OVERFLOW_VISIBLE);
return obj;
}
void lv_pointer_set_value(lv_obj_t* obj, int value)
{
lv_pointer_t* pointer = (lv_pointer_t*)obj;
if (pointer->value == value) {
return;
}
pointer->value = value;
angle_update(obj);
}
void lv_pointer_set_range(lv_obj_t* obj, int value_start, int value_range,
int angle_start, int angle_range)
{
lv_pointer_t* pointer = (lv_pointer_t*)obj;
pointer->value_start = value_start;
pointer->value_range = value_range;
pointer->angle_start = angle_start;
pointer->angle_range = angle_range;
/* update angle */
angle_update(obj);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void lv_pointer_constructor(const lv_obj_class_t* class_p,
lv_obj_t* obj)
{
LV_UNUSED(class_p);
LV_TRACE_OBJ_CREATE("begin");
lv_pointer_t* pointer = (lv_pointer_t*)obj;
/* set default range parameters */
pointer->angle_start = 0;
pointer->angle_range = 360 * 10;
pointer->value_start = 0;
pointer->value_range = 100;
LV_TRACE_OBJ_CREATE("finished");
}
static void angle_update(lv_obj_t* obj)
{
lv_pointer_t* pointer = (lv_pointer_t*)obj;
int angle = 0;
int value = pointer->value;
int value_start = pointer->value_start;
int value_range = pointer->value_range;
int angle_start = pointer->angle_start;
int angle_range = pointer->angle_range;
if (value_range != 0) {
/* Check value overflow, overwrite angle if so. */
int delta = value - value_start;
angle = angle_start;
angle += (delta * angle_range) / value_range;
/* check overflow */
if (value_range > 0) {
if (delta > value_range)
angle = angle_start + angle_range;
else if (value < value_start)
angle = angle_start;
} else { /* case of value_range < 0 */
if (delta < value_range)
angle = angle_start + angle_range;
else if (value > value_start)
angle = angle_start;
}
while (angle >= 3600)
angle -= 3600;
while (angle < 0)
angle += 3600;
}
if (angle == lv_img_get_angle(obj)) {
/* not changed */
return;
}
lv_img_set_angle(obj, angle);
}
#endif
+67
View File
@@ -0,0 +1,67 @@
#ifndef LV_WIDGETS_POINTER_H_
#define LV_WIDGETS_POINTER_H_
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include <lvgl.h>
#if LV_USE_POINTER
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_img_t obj;
int value;
int value_start;
int value_range;
int angle_start;
int angle_range;
} lv_pointer_t;
extern const lv_obj_class_t lv_pointer_class;
/**********************
* GLOBAL PROTOTYPES
**********************/
lv_obj_t* lv_pointer_create(lv_obj_t* parent);
/**
* Set range parameters for pointer
* @param value_start the value mapped to angle_start
* @param value_range the value range, could be negative
* @param angle_start the angle will be set then value equals to value_start
* @param angle_range the angle range, could be negative
*/
void lv_pointer_set_range(lv_obj_t* obj, int value_start, int value_range,
int angle_start, int angle_range);
/**
* Set current value pointer points to
* @param value If value is out of range, then angle is also clampped to limits
*/
void lv_pointer_set_value(lv_obj_t* obj, int value);
/**********************
* MACROS
**********************/
#endif /* */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* LV_WIDGETS_POINTER_H_ */
+101
View File
@@ -0,0 +1,101 @@
#include <lauxlib.h>
#include <lua.h>
#include <lvgl.h>
#include <stdlib.h>
#include <luavgl.h>
#include "lv_pointer.h"
static int luavgl_pointer_create(lua_State *L)
{
return luavgl_obj_create_helper(L, lv_pointer_create);
}
static void _lv_pointer_set_range(void *obj, lua_State *L)
{
if (!lua_istable(L, -1)) {
luaL_argerror(L, -1, "expect date table.");
return;
}
uint32_t value_start, value_range, angle_start, angle_range;
lua_getfield(L, -1, "valueStart");
value_start = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "valueRange");
value_range = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "angleStart");
angle_start = lua_tointeger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "angleRange");
angle_range = lua_tointeger(L, -1);
lua_pop(L, 1);
lv_pointer_set_range(obj, value_start, value_range, angle_start,
angle_range);
}
/* clang-format off */
static const luavgl_value_setter_t pointer_property_table[] = {
{"range", SETTER_TYPE_STACK, {.setter_stack = _lv_pointer_set_range}},
{"value", SETTER_TYPE_INT, {.setter = (setter_int_t)lv_pointer_set_value}},
};
/* clang-format on */
static int luavgl_pointer_set_property_kv(lua_State *L, void *data)
{
lv_obj_t *obj = data;
int ret = luavgl_set_property(L, obj, pointer_property_table);
if (ret == 0) {
return 0;
}
/* a base obj property? */
ret = luavgl_img_set_property_kv(L, obj);
if (ret != 0) {
printf("unkown property for pointer: %s\n", lua_tostring(L, -2));
}
return -1;
}
static int luavgl_pointer_set(lua_State *L)
{
lv_obj_t *obj = luavgl_to_obj(L, 1);
if (!lua_istable(L, -1)) {
luaL_error(L, "expect a table on 2nd para.");
return 0;
}
luavgl_iterate(L, -1, luavgl_pointer_set_property_kv, obj);
return 0;
}
static const luaL_Reg luavgl_pointer_methods[] = {
{"set", luavgl_pointer_set},
{NULL, NULL },
};
void luavgl_pointer_init(lua_State *L)
{
luavgl_obj_newmetatable(L, &lv_pointer_class, "lv_pointer",
luavgl_pointer_methods);
lua_pop(L, 1);
luaL_getmetatable(L, "widgets");
lua_getfield(L, -1, "__index");
lua_pushcfunction(L, luavgl_pointer_create);
lua_setfield(L, -2, "Pointer");
lua_pop(L, 2);
}
+8
View File
@@ -0,0 +1,8 @@
#include "widgets.h"
void luavgl_widgets_init(lua_State *L)
{
luavgl_extension_init(L);
luavgl_pointer_init(L);
luavgl_analog_time_init(L);
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef WIDGETS_WIDGETS_H_
#define WIDGETS_WIDGETS_H_
#include <lua.h>
void luavgl_extension_init(lua_State *L);
void luavgl_pointer_init(lua_State *L);
void luavgl_analog_time_init(lua_State *L);
void luavgl_widgets_init(lua_State *L);
#endif /* WIDGETS_WIDGETS_H_ */
+104
View File
@@ -0,0 +1,104 @@
---@meta
lvgl = require "lvgl"
---
--- Create Extension widget on parent
--- @param parent? Object | nil
--- @param property? ObjectStyle
--- @return Extension
function lvgl.Extension(parent, property)
end
--- Create Extension widget on obj
--- @param property? ObjectStyle
--- @return Extension
function obj:Extension(property)
end
---
--- Extension widget
---@class Extension:Object
---
local extension = {}
--- set method
--- @param p ObjectStyle
--- @return nil
function extension:set(p)
end
---
--- Create Pointer widget
--- @param parent? Object | nil
--- @param property? ObjectStyle
--- @return Pointer
function lvgl.Pointer(parent, property)
end
--- Create Extension widget on obj
--- @param property? ObjectStyle
--- @return Extension
function obj:Pointer(property)
end
---
--- Pointer widget
---@class Pointer:Object
---
local pointer = {}
--- set method
--- @param p ObjectStyle
--- @return nil
function pointer:set(p)
end
---
--- Create AnalogTime widget on parent
--- @param parent? Object | nil
--- @param property? AnalogTimeStyle
--- @return AnalogTime
function lvgl.AnalogTime(parent, property)
end
--- Create AnalogTime widget on obj
--- @param property? AnalogTimeStyle
--- @return AnalogTime
function obj:AnalogTime(property)
end
---
--- Extension widget
---@class AnalogTime:Object
---
local analogTime = {}
--- set method
--- @param p AnalogTimeStyle
--- @return nil
function analogTime:set(p)
end
--- Pause the hand refresh timer
function analogTime:pause()
end
--- Resume the hand refresh timer
function analogTime:resume()
end
--- Analog time hands parameter
--- @class AnalogTimeHands
--- @field hour string Image source path for hour hand
--- @field minute string minute hand
--- @field second string second hand
---
--- Analog time widget property
--- @class AnalogTimeStyle :StyleProp
--- @field hands AnalogTimeHands Hands images
--- @field period integer Timer refresh period, default to 1s/1min depending on whether there's second/min hands
---