1 /**
2  * @file lv_fragment.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 
10 #include "lv_fragment_private.h"
11 
12 #if LV_USE_FRAGMENT
13 #include "../../stdlib/lv_string.h"
14 
15 /**********************
16  *  STATIC PROTOTYPES
17  **********************/
18 
19 static void cb_delete_assertion(lv_event_t * event);
20 
21 /**********************
22  *   GLOBAL FUNCTIONS
23  **********************/
24 
lv_fragment_create(const lv_fragment_class_t * cls,void * args)25 lv_fragment_t * lv_fragment_create(const lv_fragment_class_t * cls, void * args)
26 {
27     LV_ASSERT_NULL(cls);
28     LV_ASSERT_NULL(cls->create_obj_cb);
29     LV_ASSERT(cls->instance_size >= sizeof(lv_fragment_t));
30     lv_fragment_t * instance = lv_malloc_zeroed(cls->instance_size);
31     instance->cls = cls;
32     instance->child_manager = lv_fragment_manager_create(instance);
33     if(cls->constructor_cb) {
34         cls->constructor_cb(instance, args);
35     }
36     return instance;
37 }
38 
lv_fragment_delete(lv_fragment_t * fragment)39 void lv_fragment_delete(lv_fragment_t * fragment)
40 {
41     LV_ASSERT_NULL(fragment);
42     if(fragment->managed) {
43         lv_fragment_manager_remove(fragment->managed->manager, fragment);
44         return;
45     }
46     if(fragment->obj) {
47         lv_fragment_delete_obj(fragment);
48     }
49     /* Objects will leak if this function called before objects deleted */
50     const lv_fragment_class_t * cls = fragment->cls;
51     if(cls->destructor_cb) {
52         cls->destructor_cb(fragment);
53     }
54     lv_fragment_manager_delete(fragment->child_manager);
55     lv_free(fragment);
56 }
57 
lv_fragment_get_manager(lv_fragment_t * fragment)58 lv_fragment_manager_t * lv_fragment_get_manager(lv_fragment_t * fragment)
59 {
60     LV_ASSERT_NULL(fragment);
61     LV_ASSERT_NULL(fragment->managed);
62     return fragment->managed->manager;
63 }
64 
lv_fragment_get_container(lv_fragment_t * fragment)65 lv_obj_t * const * lv_fragment_get_container(lv_fragment_t * fragment)
66 {
67     LV_ASSERT_NULL(fragment);
68     LV_ASSERT_NULL(fragment->managed);
69     return fragment->managed->container;
70 }
71 
lv_fragment_get_parent(lv_fragment_t * fragment)72 lv_fragment_t * lv_fragment_get_parent(lv_fragment_t * fragment)
73 {
74     LV_ASSERT_NULL(fragment);
75     LV_ASSERT_NULL(fragment->managed);
76     return lv_fragment_manager_get_parent_fragment(fragment->managed->manager);
77 }
78 
lv_fragment_create_obj(lv_fragment_t * fragment,lv_obj_t * container)79 lv_obj_t * lv_fragment_create_obj(lv_fragment_t * fragment, lv_obj_t * container)
80 {
81     lv_fragment_managed_states_t * states = fragment->managed;
82     if(states) {
83         states->destroying_obj = false;
84     }
85     const lv_fragment_class_t * cls = fragment->cls;
86     lv_obj_t * obj = cls->create_obj_cb(fragment, container);
87     LV_ASSERT_NULL(obj);
88     fragment->obj = obj;
89     lv_fragment_manager_create_obj(fragment->child_manager);
90     if(states) {
91         states->obj_created = true;
92         lv_obj_add_event_cb(obj, cb_delete_assertion, LV_EVENT_DELETE, NULL);
93     }
94     if(cls->obj_created_cb) {
95         cls->obj_created_cb(fragment, obj);
96     }
97     return obj;
98 }
99 
lv_fragment_delete_obj(lv_fragment_t * fragment)100 void lv_fragment_delete_obj(lv_fragment_t * fragment)
101 {
102     LV_ASSERT_NULL(fragment);
103     lv_fragment_manager_delete_obj(fragment->child_manager);
104     lv_fragment_managed_states_t * states = fragment->managed;
105     if(states) {
106         if(!states->obj_created) return;
107         states->destroying_obj = true;
108 
109         uint32_t i;
110         uint32_t event_cnt = lv_obj_get_event_count(fragment->obj);
111         bool cb_removed = false;
112         for(i = 0; i < event_cnt; i++) {
113             lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(fragment->obj, i);
114             if(lv_event_dsc_get_cb(event_dsc) == cb_delete_assertion) {
115                 cb_removed = lv_obj_remove_event(fragment->obj, i);
116                 break;
117             }
118         }
119 
120         LV_ASSERT(cb_removed);
121     }
122     LV_ASSERT_NULL(fragment->obj);
123     const lv_fragment_class_t * cls = fragment->cls;
124     if(cls->obj_will_delete_cb) {
125         cls->obj_will_delete_cb(fragment, fragment->obj);
126     }
127     lv_obj_delete(fragment->obj);
128     if(cls->obj_deleted_cb) {
129         cls->obj_deleted_cb(fragment, fragment->obj);
130     }
131     if(states) {
132         states->obj_created = false;
133     }
134     fragment->obj = NULL;
135 }
136 
lv_fragment_recreate_obj(lv_fragment_t * fragment)137 void lv_fragment_recreate_obj(lv_fragment_t * fragment)
138 {
139     LV_ASSERT_NULL(fragment);
140     LV_ASSERT_NULL(fragment->managed);
141     lv_fragment_delete_obj(fragment);
142     lv_fragment_create_obj(fragment, *fragment->managed->container);
143 }
144 
145 /**********************
146  *   STATIC FUNCTIONS
147  **********************/
148 
cb_delete_assertion(lv_event_t * event)149 static void cb_delete_assertion(lv_event_t * event)
150 {
151     LV_UNUSED(event);
152     LV_ASSERT_MSG(0, "Please delete objects with lv_fragment_destroy_obj");
153 }
154 
155 #endif /*LV_USE_FRAGMENT*/
156