1 /**
2  * @file lv_obj_class.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_obj.h"
10 #include "lv_theme.h"
11 
12 /*********************
13  *      DEFINES
14  *********************/
15 #define MY_CLASS &lv_obj_class
16 
17 /**********************
18  *      TYPEDEFS
19  **********************/
20 
21 /**********************
22  *  GLOBAL PROTOTYPES
23  **********************/
24 
25 /**********************
26  *  STATIC PROTOTYPES
27  **********************/
28 static void lv_obj_construct(lv_obj_t * obj);
29 static uint32_t get_instance_size(const lv_obj_class_t * class_p);
30 
31 /**********************
32  *  STATIC VARIABLES
33  **********************/
34 
35 /**********************
36  *      MACROS
37  **********************/
38 
39 /**********************
40  *   GLOBAL FUNCTIONS
41  **********************/
42 
lv_obj_class_create_obj(const lv_obj_class_t * class_p,lv_obj_t * parent)43 lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * parent)
44 {
45     LV_TRACE_OBJ_CREATE("Creating object with %p class on %p parent", (void *)class_p, (void *)parent);
46     uint32_t s = get_instance_size(class_p);
47     lv_obj_t * obj = lv_mem_alloc(s);
48     if(obj == NULL) return NULL;
49     lv_memset_00(obj, s);
50     obj->class_p = class_p;
51     obj->parent = parent;
52 
53     /*Create a screen*/
54     if(parent == NULL) {
55         LV_TRACE_OBJ_CREATE("creating a screen");
56         lv_disp_t * disp = lv_disp_get_default();
57         if(!disp) {
58             LV_LOG_WARN("No display created yet. No place to assign the new screen");
59             lv_mem_free(obj);
60             return NULL;
61         }
62 
63         if(disp->screens == NULL) {
64             disp->screens = lv_mem_alloc(sizeof(lv_obj_t *));
65             disp->screens[0] = obj;
66             disp->screen_cnt = 1;
67         }
68         else {
69             disp->screen_cnt++;
70             disp->screens = lv_mem_realloc(disp->screens, sizeof(lv_obj_t *) * disp->screen_cnt);
71             disp->screens[disp->screen_cnt - 1] = obj;
72         }
73 
74         /*Set coordinates to full screen size*/
75         obj->coords.x1 = 0;
76         obj->coords.y1 = 0;
77         obj->coords.x2 = lv_disp_get_hor_res(NULL) - 1;
78         obj->coords.y2 = lv_disp_get_ver_res(NULL) - 1;
79     }
80     /*Create a normal object*/
81     else {
82         LV_TRACE_OBJ_CREATE("creating normal object");
83         LV_ASSERT_OBJ(parent, MY_CLASS);
84         if(parent->spec_attr == NULL) {
85             lv_obj_allocate_spec_attr(parent);
86         }
87 
88         if(parent->spec_attr->children == NULL) {
89             parent->spec_attr->children = lv_mem_alloc(sizeof(lv_obj_t *));
90             parent->spec_attr->children[0] = obj;
91             parent->spec_attr->child_cnt = 1;
92         }
93         else {
94             parent->spec_attr->child_cnt++;
95             parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children,
96                                                          sizeof(lv_obj_t *) * parent->spec_attr->child_cnt);
97             parent->spec_attr->children[parent->spec_attr->child_cnt - 1] = obj;
98         }
99     }
100 
101     return obj;
102 }
103 
lv_obj_class_init_obj(lv_obj_t * obj)104 void lv_obj_class_init_obj(lv_obj_t * obj)
105 {
106     lv_obj_mark_layout_as_dirty(obj);
107     lv_obj_enable_style_refresh(false);
108 
109     lv_theme_apply(obj);
110     lv_obj_construct(obj);
111 
112     lv_obj_enable_style_refresh(true);
113     lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
114 
115     lv_obj_refresh_self_size(obj);
116 
117     lv_group_t * def_group = lv_group_get_default();
118     if(def_group && lv_obj_is_group_def(obj)) {
119         lv_group_add_obj(def_group, obj);
120     }
121 
122     lv_obj_t * parent = lv_obj_get_parent(obj);
123     if(parent) {
124         /*Call the ancestor's event handler to the parent to notify it about the new child.
125          *Also triggers layout update*/
126         lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj);
127         lv_event_send(parent, LV_EVENT_CHILD_CREATED, obj);
128 
129         /*Invalidate the area if not screen created*/
130         lv_obj_invalidate(obj);
131     }
132 }
133 
_lv_obj_destruct(lv_obj_t * obj)134 void _lv_obj_destruct(lv_obj_t * obj)
135 {
136     if(obj->class_p->destructor_cb) obj->class_p->destructor_cb(obj->class_p, obj);
137 
138     if(obj->class_p->base_class) {
139         /*Don't let the descendant methods run during destructing the ancestor type*/
140         obj->class_p = obj->class_p->base_class;
141 
142         /*Call the base class's destructor too*/
143         _lv_obj_destruct(obj);
144     }
145 }
146 
lv_obj_is_editable(lv_obj_t * obj)147 bool lv_obj_is_editable(lv_obj_t * obj)
148 {
149     const lv_obj_class_t * class_p = obj->class_p;
150 
151     /*Find a base in which editable is set*/
152     while(class_p && class_p->editable == LV_OBJ_CLASS_EDITABLE_INHERIT) class_p = class_p->base_class;
153 
154     if(class_p == NULL) return false;
155 
156     return class_p->editable == LV_OBJ_CLASS_EDITABLE_TRUE ? true : false;
157 }
158 
lv_obj_is_group_def(lv_obj_t * obj)159 bool lv_obj_is_group_def(lv_obj_t * obj)
160 {
161     const lv_obj_class_t * class_p = obj->class_p;
162 
163     /*Find a base in which group_def is set*/
164     while(class_p && class_p->group_def == LV_OBJ_CLASS_GROUP_DEF_INHERIT) class_p = class_p->base_class;
165 
166     if(class_p == NULL) return false;
167 
168     return class_p->group_def == LV_OBJ_CLASS_GROUP_DEF_TRUE ? true : false;
169 }
170 
171 /**********************
172  *   STATIC FUNCTIONS
173  **********************/
174 
lv_obj_construct(lv_obj_t * obj)175 static void lv_obj_construct(lv_obj_t * obj)
176 {
177     const lv_obj_class_t * original_class_p = obj->class_p;
178 
179     if(obj->class_p->base_class) {
180         /*Don't let the descendant methods run during constructing the ancestor type*/
181         obj->class_p = obj->class_p->base_class;
182 
183         /*Construct the base first*/
184         lv_obj_construct(obj);
185     }
186 
187     /*Restore the original class*/
188     obj->class_p = original_class_p;
189 
190     if(obj->class_p->constructor_cb) obj->class_p->constructor_cb(obj->class_p, obj);
191 }
192 
get_instance_size(const lv_obj_class_t * class_p)193 static uint32_t get_instance_size(const lv_obj_class_t * class_p)
194 {
195     /*Find a base in which instance size is set*/
196     const lv_obj_class_t * base = class_p;
197     while(base && base->instance_size == 0) base = base->base_class;
198 
199     if(base == NULL) return 0;  /*Never happens: set at least in `lv_obj` class*/
200 
201     return base->instance_size;
202 }
203