/** * @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"); lv_mem_free(obj); 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; }