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             return NULL;
60         }
61 
62         if(disp->screens == NULL) {
63             disp->screens = lv_mem_alloc(sizeof(lv_obj_t *));
64             disp->screens[0] = obj;
65             disp->screen_cnt = 1;
66         }
67         else {
68             disp->screen_cnt++;
69             disp->screens = lv_mem_realloc(disp->screens, sizeof(lv_obj_t *) * disp->screen_cnt);
70             disp->screens[disp->screen_cnt - 1] = obj;
71         }
72 
73         /*Set coordinates to full screen size*/
74         obj->coords.x1 = 0;
75         obj->coords.y1 = 0;
76         obj->coords.x2 = lv_disp_get_hor_res(NULL) - 1;
77         obj->coords.y2 = lv_disp_get_ver_res(NULL) - 1;
78     }
79     /*Create a normal object*/
80     else {
81         LV_TRACE_OBJ_CREATE("creating normal object");
82         LV_ASSERT_OBJ(parent, MY_CLASS);
83         if(parent->spec_attr == NULL) {
84             lv_obj_allocate_spec_attr(parent);
85         }
86 
87         if(parent->spec_attr->children == NULL) {
88             parent->spec_attr->children = lv_mem_alloc(sizeof(lv_obj_t *));
89             parent->spec_attr->children[0] = obj;
90             parent->spec_attr->child_cnt = 1;
91         }
92         else {
93             parent->spec_attr->child_cnt++;
94             parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children,
95                                                          sizeof(lv_obj_t *) * parent->spec_attr->child_cnt);
96             parent->spec_attr->children[parent->spec_attr->child_cnt - 1] = obj;
97         }
98     }
99 
100     return obj;
101 }
102 
lv_obj_class_init_obj(lv_obj_t * obj)103 void lv_obj_class_init_obj(lv_obj_t * obj)
104 {
105     lv_obj_mark_layout_as_dirty(obj);
106     lv_obj_enable_style_refresh(false);
107 
108     lv_theme_apply(obj);
109     lv_obj_construct(obj);
110 
111     lv_obj_enable_style_refresh(true);
112     lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
113 
114     lv_obj_refresh_self_size(obj);
115 
116     lv_group_t * def_group = lv_group_get_default();
117     if(def_group && lv_obj_is_group_def(obj)) {
118         lv_group_add_obj(def_group, obj);
119     }
120 
121     lv_obj_t * parent = lv_obj_get_parent(obj);
122     if(parent) {
123         /*Call the ancestor's event handler to the parent to notify it about the new child.
124          *Also triggers layout update*/
125         lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj);
126         lv_event_send(parent, LV_EVENT_CHILD_CREATED, obj);
127 
128         /*Invalidate the area if not screen created*/
129         lv_obj_invalidate(obj);
130     }
131 }
132 
_lv_obj_destruct(lv_obj_t * obj)133 void _lv_obj_destruct(lv_obj_t * obj)
134 {
135     if(obj->class_p->destructor_cb) obj->class_p->destructor_cb(obj->class_p, obj);
136 
137     if(obj->class_p->base_class) {
138         /*Don't let the descendant methods run during destructing the ancestor type*/
139         obj->class_p = obj->class_p->base_class;
140 
141         /*Call the base class's destructor too*/
142         _lv_obj_destruct(obj);
143     }
144 }
145 
lv_obj_is_editable(lv_obj_t * obj)146 bool lv_obj_is_editable(lv_obj_t * obj)
147 {
148     const lv_obj_class_t * class_p = obj->class_p;
149 
150     /*Find a base in which editable is set*/
151     while(class_p && class_p->editable == LV_OBJ_CLASS_EDITABLE_INHERIT) class_p = class_p->base_class;
152 
153     if(class_p == NULL) return false;
154 
155     return class_p->editable == LV_OBJ_CLASS_EDITABLE_TRUE ? true : false;
156 }
157 
lv_obj_is_group_def(lv_obj_t * obj)158 bool lv_obj_is_group_def(lv_obj_t * obj)
159 {
160     const lv_obj_class_t * class_p = obj->class_p;
161 
162     /*Find a base in which group_def is set*/
163     while(class_p && class_p->group_def == LV_OBJ_CLASS_GROUP_DEF_INHERIT) class_p = class_p->base_class;
164 
165     if(class_p == NULL) return false;
166 
167     return class_p->group_def == LV_OBJ_CLASS_GROUP_DEF_TRUE ? true : false;
168 }
169 
170 /**********************
171  *   STATIC FUNCTIONS
172  **********************/
173 
lv_obj_construct(lv_obj_t * obj)174 static void lv_obj_construct(lv_obj_t * obj)
175 {
176     const lv_obj_class_t * original_class_p = obj->class_p;
177 
178     if(obj->class_p->base_class) {
179         /*Don't let the descendant methods run during constructing the ancestor type*/
180         obj->class_p = obj->class_p->base_class;
181 
182         /*Construct the base first*/
183         lv_obj_construct(obj);
184     }
185 
186     /*Restore the original class*/
187     obj->class_p = original_class_p;
188 
189     if(obj->class_p->constructor_cb) obj->class_p->constructor_cb(obj->class_p, obj);
190 }
191 
get_instance_size(const lv_obj_class_t * class_p)192 static uint32_t get_instance_size(const lv_obj_class_t * class_p)
193 {
194     /*Find a base in which instance size is set*/
195     const lv_obj_class_t * base = class_p;
196     while(base && base->instance_size == 0) base = base->base_class;
197 
198     if(base == NULL) return 0;  /*Never happens: set at least in `lv_obj` class*/
199 
200     return base->instance_size;
201 }
202