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