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