feat(obj): add obj_id, class names, and dump support (#4536)

Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
Neo Xu
2023-09-25 16:58:36 +08:00
committed by GitHub
parent 87d323f240
commit 27357d5139
61 changed files with 499 additions and 74 deletions

View File

@@ -61,6 +61,15 @@ menu "LVGL configuration"
default 0x00FF00
help
See misc/lv_color.h for some color values examples.
config LV_USE_OBJ_ID
bool "Add id field to obj."
default n
config LV_USE_OBJ_ID_BUILTIN
bool "Use builtin method to deal with obj ID"
default n
endmenu
menu "Memory settings"

View File

@@ -34,6 +34,8 @@ static lv_obj_t * main_page;
static lv_obj_t * ta;
static const char * mbox_buttons[] = {"Ok", "Cancel", ""};
static uint32_t mem_free_start = 0;
static int16_t g_state = -1;
/**********************
* MACROS
**********************/
@@ -45,7 +47,13 @@ static uint32_t mem_free_start = 0;
void lv_demo_stress(void)
{
LV_LOG_USER("Starting stress test. (< 100 bytes permanent memory leak is normal due to fragmentation)");
lv_timer_create(obj_test_task_cb, LV_DEMO_STRESS_TIME_STEP, NULL);
lv_timer_t * t = lv_timer_create(obj_test_task_cb, LV_DEMO_STRESS_TIME_STEP, NULL);
lv_timer_ready(t); /*Prepare the test right now in first state change.*/
}
bool lv_demo_stress_finished(void)
{
return g_state == -1;
}
/**********************
@@ -55,12 +63,11 @@ void lv_demo_stress(void)
static void obj_test_task_cb(lv_timer_t * tmr)
{
(void) tmr; /*Unused*/
static int16_t state = -1;
lv_anim_t a;
lv_obj_t * obj;
switch(state) {
switch(g_state) {
case -1: {
lv_result_t res = lv_mem_test();
if(res != LV_RESULT_OK) {
@@ -404,13 +411,13 @@ static void obj_test_task_cb(lv_timer_t * tmr)
case 31:
lv_obj_clean(lv_scr_act());
main_page = NULL;
state = -2;
g_state = -2;
break;
default:
break;
}
state++;
g_state++;
}
static void auto_del(lv_obj_t * obj, uint32_t delay)

View File

@@ -30,6 +30,11 @@ extern "C" {
**********************/
void lv_demo_stress(void);
/**
* Check if stress demo has finished one round.
*/
bool lv_demo_stress_finished(void);
/**********************
* MACROS
**********************/

View File

@@ -13,3 +13,4 @@ Others
msg
imgfont
ime_pinyin
obj_id

52
docs/others/obj_id.rst Normal file
View File

@@ -0,0 +1,52 @@
======
OBJ ID
======
LVGL provides an optional field in `lv_obj_t` to store the object ID.
Object ID can be used in many cases, for example, to identify the object.
Or we can store a program backtrace to where the object is created.
Usage
-----
Enable this feature by setting ``LV_USE_OBJ_ID`` to 1 in `lv_conf.h`.
Use the builtin obj ID generator by setting ``LV_USE_OBJ_ID_BUILTIN`` to 1.
Otherwise provide your own custom implementation.
The ID is automatically generated and assigned to `obj->id` during obj's
construction by calling API `lv_obj_assign_id(obj)` from ``lv_obj_constructor``.
You can directly access the ID by `obj->id` or use API ``lv_obj_stringify_id(obj, buf, len)``
to get a string representation of the ID.
Use custom ID generator
~~~~~~~~~~~~~~~~~~~~~~~
Set `LV_USE_OBJ_ID_BUILTIN` to 0 in `lv_conf.h`. Below APIs needed to be impemented and
linked to lvgl.
.. code:: c
void lv_obj_assign_id(const lv_obj_class_t * class_p, lv_obj_t * obj);
void lv_obj_free_id(lv_obj_t * obj);
const char * lv_obj_stringify_id(lv_obj_t * obj, char * buf, uint32_t len);
:c:func:``lv_obj_assign_id`` is called when an object is created. The object final class is passed from
parameter ``class_p``. Note it may be different than ``obj->class_p`` which is the class
currently being constructed.
:c:func:``lv_obj_free_id`` is called when object is deconstructed. Free any resource alloced in ``lv_obj_assign_id``.
:c:func:``lv_obj_stringify_id`` converts id to a string representation. The string is stored in ``buf``.
Dump obj tree
~~~~~~~~~~~~~
Use API ``lv_obj_dump_tree(lv_obj_t * obj, int depth)`` to dump the object tree.
It will walk through all children and print the object ID together with object address.
This is useful to debug UI crash. From log we can rebuilt UI the moment before crash.
For example, if the obj is stored to a timer->user_data, but obj is deleted when timer expired.
Timer callback will crash because of accessing wild pointer.
From the dump log we can clearly see that the obj does not exist.

View File

@@ -264,7 +264,13 @@
/* Add 2 x 32 bit variables to each lv_obj_t to speed up getting style properties */
#define LV_OBJ_STYLE_CACHE 1
#define LV_OBJ_STYLE_CACHE 0
/* Add `id` field to `lv_obj_t` */
#define LV_USE_OBJ_ID 0
/* Use lvgl builtin method for obj ID */
#define LV_USE_OBJ_ID_BUILTIN 0
/*=====================
* COMPILER SETTINGS

View File

@@ -187,6 +187,11 @@ typedef struct _lv_global_t {
#if LV_USE_IME_PINYIN != 0
size_t ime_cand_len;
#endif
#if LV_USE_OBJ_ID_BUILTIN
void * objid_array;
uint32_t objid_count;
#endif
} lv_global_t;

View File

@@ -49,6 +49,7 @@ static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_obj_class = {
.constructor_cb = lv_obj_constructor,
.destructor_cb = lv_obj_destructor,
@@ -59,6 +60,7 @@ const lv_obj_class_t lv_obj_class = {
.group_def = LV_OBJ_CLASS_GROUP_DEF_FALSE,
.instance_size = (sizeof(lv_obj_t)),
.base_class = NULL,
.name = "obj",
};
/**********************
@@ -306,6 +308,10 @@ static void lv_obj_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
obj->flags |= LV_OBJ_FLAG_SCROLL_WITH_ARROW;
if(parent) obj->flags |= LV_OBJ_FLAG_GESTURE_BUBBLE;
#if LV_USE_OBJ_ID
lv_obj_assign_id(class_p, obj);
#endif
LV_TRACE_OBJ_CREATE("finished");
}
@@ -341,6 +347,10 @@ static void lv_obj_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
lv_free(obj->spec_attr);
obj->spec_attr = NULL;
}
#if LV_USE_OBJ_ID
lv_obj_free_id(obj);
#endif
}
static void lv_obj_draw(lv_event_t * e)

View File

@@ -185,6 +185,9 @@ typedef struct _lv_obj_t {
uint32_t style_other_prop_is_set;
#endif
void * user_data;
#if LV_USE_OBJ_ID
void * id;
#endif
lv_area_t coords;
lv_obj_flag_t flags;
lv_state_t state;
@@ -347,6 +350,42 @@ const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj);
*/
bool lv_obj_is_valid(const lv_obj_t * obj);
#if LV_USE_OBJ_ID
/**
* Assign an id to an object if not previously assigned
* Set `LV_USE_OBJ_ID_BUILTIN` to 1 to use builtin method to generate object ID.
* Otherwise, these functions including `lv_obj_[assign|free|stringify]_id` should be implemented externally.
*
* @param class_p the class this obj belongs to. Note obj->class_p is the class currently being constructed.
* @param obj pointer to an object
*/
void lv_obj_assign_id(const lv_obj_class_t * class_p, lv_obj_t * obj);
/**
* Free resources allocated by `lv_obj_assign_id`
* @param obj pointer to an object
*/
void lv_obj_free_id(lv_obj_t * obj);
/**
* Format an object's id into a string.
* @param obj pointer to an object
* @param buf buffer to write the string into
* @param len length of the buffer
*/
const char * lv_obj_stringify_id(lv_obj_t * obj, char * buf, uint32_t len);
#if LV_USE_OBJ_ID_BUILTIN
/**
* Free resources used by builtin ID generator.
*/
void lv_objid_builtin_destroy(void);
#endif
#endif /*LV_USE_OBJ_ID*/
/**********************
* MACROS
**********************/

View File

@@ -62,6 +62,7 @@ typedef struct _lv_obj_class_t {
void (*event_cb)(const struct _lv_obj_class_t * class_p,
struct _lv_event_t * e); /**< Widget type specific event function*/
void * user_data;
const char * name;
lv_coord_t width_def;
lv_coord_t height_def;
uint32_t editable : 2; /**< Value from ::lv_obj_class_editable_t*/

View File

@@ -0,0 +1,108 @@
/**
* @file lv_obj_id.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_obj.h"
#include "lv_global.h"
#include "../osal/lv_os.h"
#include "../stdlib/lv_sprintf.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
typedef struct _class_info_t {
const lv_obj_class_t * class_p;
uint32_t obj_count;
} class_info_t;
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
#if LV_USE_OBJ_ID_BUILTIN
void lv_obj_assign_id(const lv_obj_class_t * class_p, lv_obj_t * obj)
{
LV_ASSERT(obj && class_p);
uint32_t i;
uint32_t id = 0;
lv_global_t * global = LV_GLOBAL_DEFAULT();
class_info_t * info = NULL;
if(obj == NULL || class_p == NULL) return;
if(global == NULL) return;
obj->id = NULL;
for(i = 0; i < global->objid_count; i ++) {
info = ((class_info_t *)global->objid_array) + i;
if(class_p == info->class_p) break;
}
/*Resize array*/
if(i == global->objid_count) {
void * array = lv_realloc(global->objid_array, sizeof(class_info_t) * (global->objid_count + 1));
LV_ASSERT_MALLOC(array);
if(array == NULL) return;
global->objid_array = array;
global->objid_count ++;
info = ((class_info_t *)global->objid_array) + i;
info->obj_count = 0;
info->class_p = class_p;
}
id = ++info->obj_count;
obj->id = (void *)(lv_uintptr_t)id;
}
void lv_obj_free_id(lv_obj_t * obj)
{
LV_UNUSED(obj);
}
const char * lv_obj_stringify_id(lv_obj_t * obj, char * buf, uint32_t len)
{
const char * name;
if(obj == NULL || obj->class_p == NULL) return NULL;
if(buf == NULL) return NULL;
name = obj->class_p->name;
if(name == NULL) name = "nameless";
lv_snprintf(buf, len, "%s%" LV_PRId32 "", name, (uint32_t)(lv_uintptr_t)obj->id);
return buf;
}
void lv_objid_builtin_destroy(void)
{
lv_global_t * global = LV_GLOBAL_DEFAULT();
if(global == NULL) return;
lv_free(global->objid_array);
global->objid_count = 0;
}
#endif /*LV_USE_OBJ_ID_BUILTIN*/

View File

@@ -23,6 +23,8 @@
#define MY_CLASS &lv_obj_class
#define disp_ll_p &(LV_GLOBAL_DEFAULT()->disp_ll)
#define OBJ_DUMP_STRING_LEN 128
/**********************
* TYPEDEFS
**********************/
@@ -33,6 +35,7 @@
static void lv_obj_del_async_cb(void * obj);
static void obj_del_core(lv_obj_t * obj);
static lv_obj_tree_walk_res_t walk_core(lv_obj_t * obj, lv_obj_tree_walk_cb_t cb, void * user_data);
static lv_obj_tree_walk_res_t dump_tree_core(lv_obj_t * obj, lv_coord_t depth);
/**********************
* STATIC VARIABLES
@@ -359,6 +362,23 @@ void lv_obj_tree_walk(lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * use
walk_core(start_obj, cb, user_data);
}
void lv_obj_dump_tree(lv_obj_t * start_obj)
{
if(start_obj == NULL) {
lv_display_t * disp = lv_display_get_next(NULL);
while(disp) {
uint32_t i;
for(i = 0; i < disp->screen_cnt; i++) {
dump_tree_core(disp->screens[i], 0);
}
disp = lv_display_get_next(disp);
}
}
else {
dump_tree_core(start_obj, 0);
}
}
/**********************
* STATIC FUNCTIONS
**********************/
@@ -486,3 +506,32 @@ static lv_obj_tree_walk_res_t walk_core(lv_obj_t * obj, lv_obj_tree_walk_cb_t cb
}
return LV_OBJ_TREE_WALK_NEXT;
}
static lv_obj_tree_walk_res_t dump_tree_core(lv_obj_t * obj, lv_coord_t depth)
{
lv_obj_tree_walk_res_t res;
const char * id;
#if LV_USE_OBJ_ID
char buf[OBJ_DUMP_STRING_LEN];
id = lv_obj_stringify_id(obj, buf, sizeof(buf));
if(id == NULL) id = "obj0";
#else
id = "obj0";
#endif
/*id of `obj0` is an invalid id for builtin id*/
LV_LOG_USER("parent:%p, obj:%p, id:%s;", (void *)(obj ? obj->parent : NULL), (void *)obj, id);
if(obj && obj->spec_attr && obj->spec_attr->child_cnt) {
for(uint32_t i = 0; i < obj->spec_attr->child_cnt; i++) {
res = dump_tree_core(lv_obj_get_child(obj, i), depth + 1);
if(res == LV_OBJ_TREE_WALK_END)
break;
}
return LV_OBJ_TREE_WALK_NEXT;
}
else {
return LV_OBJ_TREE_WALK_END;
}
}

View File

@@ -164,6 +164,12 @@ uint32_t lv_obj_get_index(const struct _lv_obj_t * obj);
*/
void lv_obj_tree_walk(struct _lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data);
/**
* Iterate through all children of any object and print their ID.
* @param start_obj start integrating from this object
*/
void lv_obj_dump_tree(struct _lv_obj_t * start_ob);
/**********************
* MACROS
**********************/

View File

@@ -36,7 +36,8 @@ const lv_obj_class_t lv_barcode_class = {
.destructor_cb = lv_barcode_destructor,
.width_def = LV_SIZE_CONTENT,
.instance_size = sizeof(lv_barcode_t),
.base_class = &lv_canvas_class
.base_class = &lv_canvas_class,
.name = "barcode",
};
/**********************

View File

@@ -88,11 +88,13 @@ static void lv_ffmpeg_player_destructor(const lv_obj_class_t * class_p, lv_obj_t
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_ffmpeg_player_class = {
.constructor_cb = lv_ffmpeg_player_constructor,
.destructor_cb = lv_ffmpeg_player_destructor,
.instance_size = sizeof(lv_ffmpeg_player_t),
.base_class = &lv_image_class
.base_class = &lv_image_class,
.name = "ffmpeg-player",
};
/**********************

View File

@@ -31,11 +31,13 @@ static void next_frame_task_cb(lv_timer_t * t);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_gif_class = {
.constructor_cb = lv_gif_constructor,
.destructor_cb = lv_gif_destructor,
.instance_size = sizeof(lv_gif_t),
.base_class = &lv_image_class
.base_class = &lv_image_class,
.name = "gif",
};
/**********************

View File

@@ -30,11 +30,13 @@ static void lv_qrcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_qrcode_class = {
.constructor_cb = lv_qrcode_constructor,
.destructor_cb = lv_qrcode_destructor,
.instance_size = sizeof(lv_qrcode_t),
.base_class = &lv_canvas_class
.base_class = &lv_canvas_class,
.name = "qrcode",
};
/**********************

View File

@@ -32,11 +32,13 @@ static void next_frame_task_cb(lv_timer_t * t);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_rlottie_class = {
.constructor_cb = lv_rlottie_constructor,
.destructor_cb = lv_rlottie_destructor,
.instance_size = sizeof(lv_rlottie_t),
.base_class = &lv_image_class
.base_class = &lv_image_class,
.name = "rlottie",
};
typedef struct {

View File

@@ -721,14 +721,28 @@
/* Add 2 x 32 bit variables to each lv_obj_t to speed up getting style properties */
#ifndef LV_OBJ_STYLE_CACHE
#ifdef _LV_KCONFIG_PRESENT
#ifdef CONFIG_LV_OBJ_STYLE_CACHE
#define LV_OBJ_STYLE_CACHE CONFIG_LV_OBJ_STYLE_CACHE
#else
#define LV_OBJ_STYLE_CACHE 0
#endif
#ifdef CONFIG_LV_OBJ_STYLE_CACHE
#define LV_OBJ_STYLE_CACHE CONFIG_LV_OBJ_STYLE_CACHE
#else
#define LV_OBJ_STYLE_CACHE 1
#define LV_OBJ_STYLE_CACHE 0
#endif
#endif
/* Add `id` field to `lv_obj_t` */
#ifndef LV_USE_OBJ_ID
#ifdef CONFIG_LV_USE_OBJ_ID
#define LV_USE_OBJ_ID CONFIG_LV_USE_OBJ_ID
#else
#define LV_USE_OBJ_ID 0
#endif
#endif
/* Use lvgl builtin method for obj ID */
#ifndef LV_USE_OBJ_ID_BUILTIN
#ifdef CONFIG_LV_USE_OBJ_ID_BUILTIN
#define LV_USE_OBJ_ID_BUILTIN CONFIG_LV_USE_OBJ_ID_BUILTIN
#else
#define LV_USE_OBJ_ID_BUILTIN 0
#endif
#endif

View File

@@ -310,6 +310,10 @@ void lv_deinit(void)
#if LV_USE_LOG
lv_log_register_print_cb(NULL);
#endif
#if LV_USE_OBJ_ID_BUILTIN
lv_objid_builtin_destroy();
#endif
}
#endif

View File

@@ -53,7 +53,8 @@ const lv_obj_class_t lv_file_explorer_class = {
.width_def = LV_SIZE_CONTENT,
.height_def = LV_SIZE_CONTENT,
.instance_size = sizeof(lv_file_explorer_t),
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "file-explorer",
};
/**********************

View File

@@ -48,6 +48,7 @@ static void pinyin_ime_clear_data(lv_obj_t * obj);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_ime_pinyin_class = {
.constructor_cb = lv_ime_pinyin_constructor,
.destructor_cb = lv_ime_pinyin_destructor,
@@ -55,7 +56,8 @@ const lv_obj_class_t lv_ime_pinyin_class = {
.height_def = LV_SIZE_CONTENT,
.group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE,
.instance_size = sizeof(lv_ime_pinyin_t),
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "ime-pinyin",
};
#if LV_IME_PINYIN_USE_K9_MODE

View File

@@ -57,6 +57,7 @@ static void sysmon_async_cb(void * user_data);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_sysmon_class = {
.base_class = &lv_label_class,
.constructor_cb = lv_sysmon_constructor,
@@ -64,6 +65,7 @@ const lv_obj_class_t lv_sysmon_class = {
.height_def = LV_SIZE_CONTENT,
.event_cb = lv_sysmon_event,
.instance_size = sizeof(lv_sysmon_t),
.name = "sysmon",
};
/**********************

View File

@@ -42,10 +42,12 @@ static void lv_animimg_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_animimg_class = {
.constructor_cb = lv_animimg_constructor,
.instance_size = sizeof(lv_animimg_t),
.base_class = &lv_image_class
.base_class = &lv_image_class,
.name = "animimg",
};
/**********************

View File

@@ -49,7 +49,8 @@ const lv_obj_class_t lv_arc_class = {
.event_cb = lv_arc_event,
.instance_size = sizeof(lv_arc_t),
.editable = LV_OBJ_CLASS_EDITABLE_TRUE,
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "arc",
};
/**********************

View File

@@ -64,7 +64,8 @@ const lv_obj_class_t lv_bar_class = {
.width_def = LV_DPI_DEF * 2,
.height_def = LV_DPI_DEF / 10,
.instance_size = sizeof(lv_bar_t),
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "bar",
};
/**********************

View File

@@ -33,7 +33,8 @@ const lv_obj_class_t lv_button_class = {
.height_def = LV_SIZE_CONTENT,
.group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE,
.instance_size = sizeof(lv_button_t),
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "btn",
};
/**********************

View File

@@ -70,7 +70,8 @@ const lv_obj_class_t lv_buttonmatrix_class = {
.instance_size = sizeof(lv_buttonmatrix_t),
.editable = LV_OBJ_CLASS_EDITABLE_TRUE,
.group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE,
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "btnmatrix",
};
/**********************

View File

@@ -38,13 +38,15 @@ static void highlight_update(lv_obj_t * calendar);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_calendar_class = {
.constructor_cb = lv_calendar_constructor,
.width_def = (LV_DPI_DEF * 3) / 2,
.height_def = (LV_DPI_DEF * 3) / 2,
.group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE,
.instance_size = sizeof(lv_calendar_t),
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "calendar",
};
static const char * day_names_def[7] = LV_CALENDAR_DEFAULT_DAY_NAMES;

View File

@@ -32,11 +32,13 @@ static void value_changed_event_cb(lv_event_t * e);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_calendar_header_arrow_class = {
.base_class = &lv_obj_class,
.constructor_cb = my_constructor,
.width_def = LV_PCT(100),
.height_def = LV_DPI_DEF / 3
.height_def = LV_DPI_DEF / 3,
.name = "calendar-header-arrow",
};
static const char * month_names_def[12] = LV_CALENDAR_DEFAULT_MONTH_NAMES;

View File

@@ -32,11 +32,13 @@ static void value_changed_event_cb(lv_event_t * e);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_calendar_header_dropdown_class = {
.base_class = &lv_obj_class,
.width_def = LV_PCT(100),
.height_def = LV_SIZE_CONTENT,
.constructor_cb = my_constructor
.constructor_cb = my_constructor,
.name = "calendar-header-dropdown",
};
static const char * month_list = "01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12";

View File

@@ -34,11 +34,13 @@ static void lv_canvas_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_canvas_class = {
.constructor_cb = lv_canvas_constructor,
.destructor_cb = lv_canvas_destructor,
.instance_size = sizeof(lv_canvas_t),
.base_class = &lv_image_class
.base_class = &lv_image_class,
.name = "canvas",
};
/**********************

View File

@@ -46,6 +46,7 @@ lv_chart_tick_dsc_t * get_tick_gsc(lv_obj_t * obj, lv_chart_axis_t axis);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_chart_class = {
.constructor_cb = lv_chart_constructor,
.destructor_cb = lv_chart_destructor,
@@ -53,7 +54,8 @@ const lv_obj_class_t lv_chart_class = {
.width_def = LV_PCT(100),
.height_def = LV_DPI_DEF * 2,
.instance_size = sizeof(lv_chart_t),
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "chart",
};
/**********************

View File

@@ -43,7 +43,8 @@ const lv_obj_class_t lv_checkbox_class = {
.height_def = LV_SIZE_CONTENT,
.group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE,
.instance_size = sizeof(lv_checkbox_t),
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "checkbox",
};
/**********************

View File

@@ -60,6 +60,7 @@ static lv_obj_t * get_label(const lv_obj_t * obj);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_dropdown_class = {
.constructor_cb = lv_dropdown_constructor,
.destructor_cb = lv_dropdown_destructor,
@@ -69,7 +70,8 @@ const lv_obj_class_t lv_dropdown_class = {
.instance_size = sizeof(lv_dropdown_t),
.editable = LV_OBJ_CLASS_EDITABLE_TRUE,
.group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE,
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "dropdown",
};
const lv_obj_class_t lv_dropdownlist_class = {
@@ -77,7 +79,8 @@ const lv_obj_class_t lv_dropdownlist_class = {
.destructor_cb = lv_dropdownlist_destructor,
.event_cb = lv_dropdown_list_event,
.instance_size = sizeof(lv_dropdown_list_t),
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "dropdown-list",
};

View File

@@ -38,7 +38,8 @@ const lv_obj_class_t lv_image_class = {
.width_def = LV_SIZE_CONTENT,
.height_def = LV_SIZE_CONTENT,
.instance_size = sizeof(lv_image_t),
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "image",
};
/**********************

View File

@@ -36,11 +36,13 @@ static void update_src_info(lv_imgbtn_src_info_t * info, const void * src);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_imgbtn_class = {
.base_class = &lv_obj_class,
.instance_size = sizeof(lv_imgbtn_t),
.constructor_cb = lv_imgbtn_constructor,
.event_cb = lv_imgbtn_event,
.name = "imgbtn",
};
/**********************

View File

@@ -38,13 +38,15 @@ static void lv_keyboard_update_ctrl_map(lv_obj_t * obj);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_keyboard_class = {
.constructor_cb = lv_keyboard_constructor,
.width_def = LV_PCT(100),
.height_def = LV_PCT(50),
.instance_size = sizeof(lv_keyboard_t),
.editable = 1,
.base_class = &lv_buttonmatrix_class
.base_class = &lv_buttonmatrix_class,
.name = "keyboard",
};
static const char * const default_kb_map_lc[] = {"1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", LV_SYMBOL_BACKSPACE, "\n",

View File

@@ -66,7 +66,8 @@ const lv_obj_class_t lv_label_class = {
.width_def = LV_SIZE_CONTENT,
.height_def = LV_SIZE_CONTENT,
.instance_size = sizeof(lv_label_t),
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "label",
};
/**********************

View File

@@ -31,6 +31,7 @@ static void lv_led_event(const lv_obj_class_t * class_p, lv_event_t * e);
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_led_class = {
.base_class = &lv_obj_class,
.constructor_cb = lv_led_constructor,
@@ -38,6 +39,7 @@ const lv_obj_class_t lv_led_class = {
.height_def = LV_DPI_DEF / 5,
.event_cb = lv_led_event,
.instance_size = sizeof(lv_led_t),
.name = "led",
};
/**********************

View File

@@ -40,7 +40,8 @@ const lv_obj_class_t lv_line_class = {
.width_def = LV_SIZE_CONTENT,
.height_def = LV_SIZE_CONTENT,
.instance_size = sizeof(lv_line_t),
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "line",
};
/**********************

View File

@@ -27,19 +27,21 @@
/**********************
* STATIC PROTOTYPES
**********************/
const lv_obj_class_t lv_list_class = {
.base_class = &lv_obj_class,
.width_def = (LV_DPI_DEF * 3) / 2,
.height_def = LV_DPI_DEF * 2
.height_def = LV_DPI_DEF * 2,
.name = "list",
};
const lv_obj_class_t lv_list_button_class = {
.base_class = &lv_button_class,
.name = "list-btn",
};
const lv_obj_class_t lv_list_text_class = {
.base_class = &lv_label_class,
.name = "list-text",
};
/**********************

View File

@@ -42,7 +42,8 @@ const lv_obj_class_t lv_menu_class = {
.base_class = &lv_obj_class,
.width_def = (LV_DPI_DEF * 3) / 2,
.height_def = LV_DPI_DEF * 2,
.instance_size = sizeof(lv_menu_t)
.instance_size = sizeof(lv_menu_t),
.name = "menu",
};
const lv_obj_class_t lv_menu_page_class = {
.constructor_cb = lv_menu_page_constructor,
@@ -50,43 +51,47 @@ const lv_obj_class_t lv_menu_page_class = {
.base_class = &lv_obj_class,
.width_def = LV_PCT(100),
.height_def = LV_SIZE_CONTENT,
.instance_size = sizeof(lv_menu_page_t)
.instance_size = sizeof(lv_menu_page_t),
.name = "menu-page",
};
const lv_obj_class_t lv_menu_cont_class = {
.constructor_cb = lv_menu_cont_constructor,
.base_class = &lv_obj_class,
.width_def = LV_PCT(100),
.height_def = LV_SIZE_CONTENT
.height_def = LV_SIZE_CONTENT,
.name = "menu-cont",
};
const lv_obj_class_t lv_menu_section_class = {
.constructor_cb = lv_menu_section_constructor,
.base_class = &lv_obj_class,
.width_def = LV_PCT(100),
.height_def = LV_SIZE_CONTENT
.height_def = LV_SIZE_CONTENT,
.name = "menu-section",
};
const lv_obj_class_t lv_menu_separator_class = {
.base_class = &lv_obj_class,
.width_def = LV_SIZE_CONTENT,
.height_def = LV_SIZE_CONTENT
.height_def = LV_SIZE_CONTENT,
.name = "menu-separator",
};
const lv_obj_class_t lv_menu_sidebar_cont_class = {
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
};
const lv_obj_class_t lv_menu_main_cont_class = {
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
};
const lv_obj_class_t lv_menu_main_header_cont_class = {
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
};
const lv_obj_class_t lv_menu_sidebar_header_cont_class = {
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
};
static void lv_menu_refr(lv_obj_t * obj);

View File

@@ -37,12 +37,14 @@ static void inv_line(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_meter_class = {
.constructor_cb = lv_meter_constructor,
.destructor_cb = lv_meter_destructor,
.event_cb = lv_meter_event,
.instance_size = sizeof(lv_meter_t),
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "meter",
};
/**********************

View File

@@ -39,21 +39,24 @@ const lv_obj_class_t lv_msgbox_class = {
.base_class = &lv_obj_class,
.width_def = LV_DPI_DEF * 2,
.height_def = LV_SIZE_CONTENT,
.instance_size = sizeof(lv_msgbox_t)
.instance_size = sizeof(lv_msgbox_t),
.name = "msgbox",
};
const lv_obj_class_t lv_msgbox_content_class = {
.base_class = &lv_obj_class,
.width_def = LV_PCT(100),
.height_def = LV_SIZE_CONTENT,
.instance_size = sizeof(lv_obj_t)
.instance_size = sizeof(lv_obj_t),
.name = "msgbox-content",
};
const lv_obj_class_t lv_msgbox_backdrop_class = {
.base_class = &lv_obj_class,
.width_def = LV_PCT(100),
.height_def = LV_PCT(100),
.instance_size = sizeof(lv_obj_t)
.instance_size = sizeof(lv_obj_t),
.name = "msgbox-backdrop",
};
/**********************

View File

@@ -47,7 +47,8 @@ const lv_obj_class_t lv_templ_class = {
.instance_size = sizeof(lv_templ_t),
.group_def = LV_OBJ_CLASS_GROUP_DEF_INHERIT,
.editable = LV_OBJ_CLASS_EDITABLE_INHERIT,
.base_class = &lv_templ_class
.base_class = &lv_templ_class,
.name = "templ",
};
/**********************

View File

@@ -57,13 +57,15 @@ const lv_obj_class_t lv_roller_class = {
.instance_size = sizeof(lv_roller_t),
.editable = LV_OBJ_CLASS_EDITABLE_TRUE,
.group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE,
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "roller",
};
const lv_obj_class_t lv_roller_label_class = {
.event_cb = lv_roller_label_event,
.instance_size = sizeof(lv_label_t),
.base_class = &lv_label_class
.base_class = &lv_label_class,
.name = "roller-label",
};
/**********************

View File

@@ -61,13 +61,15 @@ static void scale_build_custom_label_text(lv_obj_t * obj, lv_draw_label_dsc_t *
/**********************
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_scale_class = {
.constructor_cb = lv_scale_constructor,
.destructor_cb = lv_scale_destructor,
.event_cb = lv_scale_event,
.instance_size = sizeof(lv_scale_t),
.editable = LV_OBJ_CLASS_EDITABLE_TRUE,
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "scale",
};
/**********************

View File

@@ -50,7 +50,8 @@ const lv_obj_class_t lv_slider_class = {
.editable = LV_OBJ_CLASS_EDITABLE_TRUE,
.group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE,
.instance_size = sizeof(lv_slider_t),
.base_class = &lv_bar_class
.base_class = &lv_bar_class,
.name = "slider",
};
/**********************

View File

@@ -77,6 +77,7 @@ const lv_obj_class_t lv_spangroup_class = {
.instance_size = sizeof(lv_spangroup_t),
.width_def = LV_SIZE_CONTENT,
.height_def = LV_SIZE_CONTENT,
.name = "span",
};
/**********************

View File

@@ -41,7 +41,8 @@ const lv_obj_class_t lv_spinbox_class = {
.width_def = LV_DPI_DEF,
.instance_size = sizeof(lv_spinbox_t),
.editable = LV_OBJ_CLASS_EDITABLE_TRUE,
.base_class = &lv_textarea_class
.base_class = &lv_textarea_class,
.name = "spinbox",
};
/**********************
* MACROS

View File

@@ -31,7 +31,8 @@ static void arc_anim_end_angle(void * obj, int32_t v);
**********************/
const lv_obj_class_t lv_spinner_class = {
.base_class = &lv_arc_class,
.constructor_cb = lv_spinner_constructor
.constructor_cb = lv_spinner_constructor,
.name = "spinner",
};
/**********************

View File

@@ -58,7 +58,8 @@ const lv_obj_class_t lv_switch_class = {
.height_def = (4 * LV_DPI_DEF) / 17,
.group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE,
.instance_size = sizeof(lv_switch_t),
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "switch",
};
/**********************

View File

@@ -63,6 +63,7 @@ const lv_obj_class_t lv_table_class = {
.editable = LV_OBJ_CLASS_EDITABLE_TRUE,
.group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE,
.instance_size = sizeof(lv_table_t),
.name = "table",
};
/**********************
* MACROS

View File

@@ -40,7 +40,8 @@ const lv_obj_class_t lv_tabview_class = {
.width_def = LV_PCT(100),
.height_def = LV_PCT(100),
.base_class = &lv_obj_class,
.instance_size = sizeof(lv_tabview_t)
.instance_size = sizeof(lv_tabview_t),
.name = "tabview",
};
typedef struct {

View File

@@ -73,7 +73,8 @@ const lv_obj_class_t lv_textarea_class = {
.width_def = LV_DPI_DEF * 2,
.height_def = LV_DPI_DEF,
.instance_size = sizeof(lv_textarea_t),
.base_class = &lv_obj_class
.base_class = &lv_obj_class,
.name = "textarea",
};
static const char * ta_insert_replace;

View File

@@ -30,15 +30,19 @@ static void tileview_event_cb(lv_event_t * e);
* STATIC VARIABLES
**********************/
const lv_obj_class_t lv_tileview_class = {.constructor_cb = lv_tileview_constructor,
.base_class = &lv_obj_class,
.instance_size = sizeof(lv_tileview_t)
};
const lv_obj_class_t lv_tileview_class = {
.constructor_cb = lv_tileview_constructor,
.base_class = &lv_obj_class,
.instance_size = sizeof(lv_tileview_t),
.name = "tileview",
};
const lv_obj_class_t lv_tileview_tile_class = {.constructor_cb = lv_tileview_tile_constructor,
.base_class = &lv_obj_class,
.instance_size = sizeof(lv_tileview_tile_t)
};
const lv_obj_class_t lv_tileview_tile_class = {
.constructor_cb = lv_tileview_tile_constructor,
.base_class = &lv_obj_class,
.instance_size = sizeof(lv_tileview_tile_t),
.name = "tile",
};
/**********************
* MACROS

View File

@@ -31,7 +31,8 @@ const lv_obj_class_t lv_win_class = {
.width_def = LV_PCT(100),
.height_def = LV_PCT(100),
.base_class = &lv_obj_class,
.instance_size = sizeof(lv_win_t)
.instance_size = sizeof(lv_win_t),
.name = "win",
};
/**********************
* MACROS

View File

@@ -85,4 +85,5 @@
#define LV_USE_DEMO_MULTILANG 1
#define LV_USE_DEMO_SCROLL 1
#define LV_USE_OBJ_ID 1
#define LV_USE_OBJ_ID_BUILTIN 1

View File

@@ -10,7 +10,13 @@
static void loop_through_stress_test(void)
{
#if LV_USE_DEMO_STRESS
lv_test_indev_wait(LV_DEMO_STRESS_TIME_STEP * 33); /* FIXME: remove magic number of states */
while(1) {
lv_timer_handler();
if(lv_demo_stress_finished()) {
break;
}
lv_tick_inc(1);
}
#endif
}
void test_demo_stress(void)
@@ -21,7 +27,7 @@ void test_demo_stress(void)
/* loop once to allow objects to be created */
loop_through_stress_test();
uint32_t mem_before = lv_test_get_free_mem();
/* loop 10 more times */
/* loop 5 more times */
for(uint32_t i = 0; i < 5; i++) {
loop_through_stress_test();
}

View File

@@ -0,0 +1,29 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
void test_obj_id_should_match_class_name(void)
{
char buf[128];
lv_obj_t * obj = lv_obj_create(NULL);
lv_obj_stringify_id(obj, buf, sizeof(buf));
TEST_ASSERT_TRUE(strncmp("obj", buf, strlen("obj")) == 0);
lv_obj_t * img = lv_image_create(NULL);
lv_obj_stringify_id(img, buf, sizeof(buf));
TEST_ASSERT_TRUE(strncmp("image", buf, strlen("image")) == 0);
}
void test_obj_id_should_grow_by_one(void)
{
uint32_t id1, id2;
lv_obj_t * obj1 = lv_label_create(NULL);
id1 = (lv_uintptr_t)obj1->id;
lv_obj_t * obj2 = lv_label_create(NULL);
id2 = (lv_uintptr_t)obj2->id;
TEST_ASSERT_EQUAL(id1 + 1, id2);
}
#endif