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