lvgl_cpp/lvgl/core/lv_obj_class.c

202 lines
5.7 KiB
C
Raw Normal View History

2023-03-14 11:57:25 +00:00
/**
* @file lv_obj_class.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_obj.h"
#include "lv_theme.h"
/*********************
* DEFINES
*********************/
#define MY_CLASS &lv_obj_class
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_obj_construct(lv_obj_t * obj);
static uint32_t get_instance_size(const lv_obj_class_t * class_p);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * parent)
{
LV_TRACE_OBJ_CREATE("Creating object with %p class on %p parent", (void *)class_p, (void *)parent);
uint32_t s = get_instance_size(class_p);
lv_obj_t * obj = lv_mem_alloc(s);
if(obj == NULL) return NULL;
lv_memset_00(obj, s);
obj->class_p = class_p;
obj->parent = parent;
/*Create a screen*/
if(parent == NULL) {
LV_TRACE_OBJ_CREATE("creating a screen");
lv_disp_t * disp = lv_disp_get_default();
if(!disp) {
LV_LOG_WARN("No display created yet. No place to assign the new screen");
return NULL;
}
if(disp->screens == NULL) {
disp->screens = lv_mem_alloc(sizeof(lv_obj_t *));
disp->screens[0] = obj;
disp->screen_cnt = 1;
}
else {
disp->screen_cnt++;
disp->screens = lv_mem_realloc(disp->screens, sizeof(lv_obj_t *) * disp->screen_cnt);
disp->screens[disp->screen_cnt - 1] = obj;
}
/*Set coordinates to full screen size*/
obj->coords.x1 = 0;
obj->coords.y1 = 0;
obj->coords.x2 = lv_disp_get_hor_res(NULL) - 1;
obj->coords.y2 = lv_disp_get_ver_res(NULL) - 1;
}
/*Create a normal object*/
else {
LV_TRACE_OBJ_CREATE("creating normal object");
LV_ASSERT_OBJ(parent, MY_CLASS);
if(parent->spec_attr == NULL) {
lv_obj_allocate_spec_attr(parent);
}
if(parent->spec_attr->children == NULL) {
parent->spec_attr->children = lv_mem_alloc(sizeof(lv_obj_t *));
parent->spec_attr->children[0] = obj;
parent->spec_attr->child_cnt = 1;
}
else {
parent->spec_attr->child_cnt++;
parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children,
sizeof(lv_obj_t *) * parent->spec_attr->child_cnt);
parent->spec_attr->children[parent->spec_attr->child_cnt - 1] = obj;
}
}
return obj;
}
void lv_obj_class_init_obj(lv_obj_t * obj)
{
lv_obj_mark_layout_as_dirty(obj);
lv_obj_enable_style_refresh(false);
lv_theme_apply(obj);
lv_obj_construct(obj);
lv_obj_enable_style_refresh(true);
lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
lv_obj_refresh_self_size(obj);
lv_group_t * def_group = lv_group_get_default();
if(def_group && lv_obj_is_group_def(obj)) {
lv_group_add_obj(def_group, obj);
}
lv_obj_t * parent = lv_obj_get_parent(obj);
if(parent) {
/*Call the ancestor's event handler to the parent to notify it about the new child.
*Also triggers layout update*/
lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj);
lv_event_send(parent, LV_EVENT_CHILD_CREATED, obj);
/*Invalidate the area if not screen created*/
lv_obj_invalidate(obj);
}
}
void _lv_obj_destruct(lv_obj_t * obj)
{
if(obj->class_p->destructor_cb) obj->class_p->destructor_cb(obj->class_p, obj);
if(obj->class_p->base_class) {
/*Don't let the descendant methods run during destructing the ancestor type*/
obj->class_p = obj->class_p->base_class;
/*Call the base class's destructor too*/
_lv_obj_destruct(obj);
}
}
bool lv_obj_is_editable(lv_obj_t * obj)
{
const lv_obj_class_t * class_p = obj->class_p;
/*Find a base in which editable is set*/
while(class_p && class_p->editable == LV_OBJ_CLASS_EDITABLE_INHERIT) class_p = class_p->base_class;
if(class_p == NULL) return false;
return class_p->editable == LV_OBJ_CLASS_EDITABLE_TRUE ? true : false;
}
bool lv_obj_is_group_def(lv_obj_t * obj)
{
const lv_obj_class_t * class_p = obj->class_p;
/*Find a base in which group_def is set*/
while(class_p && class_p->group_def == LV_OBJ_CLASS_GROUP_DEF_INHERIT) class_p = class_p->base_class;
if(class_p == NULL) return false;
return class_p->group_def == LV_OBJ_CLASS_GROUP_DEF_TRUE ? true : false;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void lv_obj_construct(lv_obj_t * obj)
{
const lv_obj_class_t * original_class_p = obj->class_p;
if(obj->class_p->base_class) {
/*Don't let the descendant methods run during constructing the ancestor type*/
obj->class_p = obj->class_p->base_class;
/*Construct the base first*/
lv_obj_construct(obj);
}
/*Restore the original class*/
obj->class_p = original_class_p;
if(obj->class_p->constructor_cb) obj->class_p->constructor_cb(obj->class_p, obj);
}
static uint32_t get_instance_size(const lv_obj_class_t * class_p)
{
/*Find a base in which instance size is set*/
const lv_obj_class_t * base = class_p;
while(base && base->instance_size == 0) base = base->base_class;
if(base == NULL) return 0; /*Never happens: set at least in `lv_obj` class*/
return base->instance_size;
}