acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
lv_fragment_manager.c (8393B)
1 /** 2 * @file lv_fragment_manager.c 3 * 4 */ 5 6 /********************* 7 * INCLUDES 8 *********************/ 9 10 #include "lv_fragment.h" 11 12 #if LV_USE_FRAGMENT 13 14 #include "../../../misc/lv_ll.h" 15 16 /********************* 17 * DEFINES 18 *********************/ 19 20 /********************** 21 * TYPEDEFS 22 **********************/ 23 typedef struct _lv_fragment_stack_item_t { 24 lv_fragment_managed_states_t * states; 25 } lv_fragment_stack_item_t; 26 27 struct _lv_fragment_manager_t { 28 lv_fragment_t * parent; 29 /** 30 * Linked list to store attached fragments 31 */ 32 lv_ll_t attached; 33 /** 34 * Linked list to store fragments in stack 35 */ 36 lv_ll_t stack; 37 }; 38 39 40 /********************** 41 * STATIC PROTOTYPES 42 **********************/ 43 44 static void item_create_obj(lv_fragment_managed_states_t * item); 45 46 static void item_del_obj(lv_fragment_managed_states_t * item); 47 48 static void item_del_fragment(lv_fragment_managed_states_t * item); 49 50 static lv_fragment_managed_states_t * fragment_attach(lv_fragment_manager_t * manager, lv_fragment_t * fragment, 51 lv_obj_t * const * container); 52 53 /********************** 54 * STATIC VARIABLES 55 **********************/ 56 57 /********************** 58 * MACROS 59 **********************/ 60 61 /********************** 62 * GLOBAL FUNCTIONS 63 **********************/ 64 65 lv_fragment_manager_t * lv_fragment_manager_create(lv_fragment_t * parent) 66 { 67 lv_fragment_manager_t * instance = lv_mem_alloc(sizeof(lv_fragment_manager_t)); 68 lv_memset_00(instance, sizeof(lv_fragment_manager_t)); 69 instance->parent = parent; 70 _lv_ll_init(&instance->attached, sizeof(lv_fragment_managed_states_t)); 71 _lv_ll_init(&instance->stack, sizeof(lv_fragment_stack_item_t)); 72 return instance; 73 } 74 75 void lv_fragment_manager_del(lv_fragment_manager_t * manager) 76 { 77 LV_ASSERT_NULL(manager); 78 lv_fragment_managed_states_t * states; 79 _LV_LL_READ_BACK(&manager->attached, states) { 80 item_del_obj(states); 81 item_del_fragment(states); 82 } 83 _lv_ll_clear(&manager->attached); 84 _lv_ll_clear(&manager->stack); 85 lv_mem_free(manager); 86 } 87 88 void lv_fragment_manager_create_obj(lv_fragment_manager_t * manager) 89 { 90 LV_ASSERT_NULL(manager); 91 lv_fragment_stack_item_t * top = _lv_ll_get_tail(&manager->stack); 92 lv_fragment_managed_states_t * states = NULL; 93 _LV_LL_READ(&manager->attached, states) { 94 if(states->in_stack && top->states != states) { 95 /*Only create obj for top item in stack*/ 96 continue; 97 } 98 item_create_obj(states); 99 } 100 } 101 102 void lv_fragment_manager_del_obj(lv_fragment_manager_t * manager) 103 { 104 LV_ASSERT_NULL(manager); 105 lv_fragment_managed_states_t * states = NULL; 106 _LV_LL_READ_BACK(&manager->attached, states) { 107 item_del_obj(states); 108 } 109 } 110 111 void lv_fragment_manager_add(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container) 112 { 113 lv_fragment_managed_states_t * states = fragment_attach(manager, fragment, container); 114 if(!manager->parent || manager->parent->managed->obj_created) { 115 item_create_obj(states); 116 } 117 } 118 119 void lv_fragment_manager_remove(lv_fragment_manager_t * manager, lv_fragment_t * fragment) 120 { 121 LV_ASSERT_NULL(manager); 122 LV_ASSERT_NULL(fragment); 123 LV_ASSERT_NULL(fragment->managed); 124 LV_ASSERT(fragment->managed->manager == manager); 125 lv_fragment_managed_states_t * states = fragment->managed; 126 lv_fragment_managed_states_t * prev = NULL; 127 bool was_top = false; 128 if(states->in_stack) { 129 void * stack_top = _lv_ll_get_tail(&manager->stack); 130 lv_fragment_stack_item_t * stack = NULL; 131 _LV_LL_READ_BACK(&manager->stack, stack) { 132 if(stack->states == states) { 133 was_top = stack_top == stack; 134 void * stack_prev = _lv_ll_get_prev(&manager->stack, stack); 135 if(!stack_prev) break; 136 prev = ((lv_fragment_stack_item_t *) stack_prev)->states; 137 break; 138 } 139 } 140 if(stack) { 141 _lv_ll_remove(&manager->stack, stack); 142 } 143 } 144 item_del_obj(states); 145 item_del_fragment(states); 146 _lv_ll_remove(&manager->attached, states); 147 if(prev && was_top) { 148 item_create_obj(prev); 149 } 150 } 151 152 void lv_fragment_manager_push(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container) 153 { 154 lv_fragment_stack_item_t * top = _lv_ll_get_tail(&manager->stack); 155 if(top != NULL) { 156 item_del_obj(top->states); 157 } 158 lv_fragment_managed_states_t * states = fragment_attach(manager, fragment, container); 159 states->in_stack = true; 160 /*Add fragment to the top of the stack*/ 161 lv_fragment_stack_item_t * item = _lv_ll_ins_tail(&manager->stack); 162 lv_memset_00(item, sizeof(lv_fragment_stack_item_t)); 163 item->states = states; 164 item_create_obj(states); 165 } 166 167 bool lv_fragment_manager_pop(lv_fragment_manager_t * manager) 168 { 169 lv_fragment_t * top = lv_fragment_manager_get_top(manager); 170 if(top == NULL) return false; 171 lv_fragment_manager_remove(manager, top); 172 return true; 173 } 174 175 void lv_fragment_manager_replace(lv_fragment_manager_t * manager, lv_fragment_t * fragment, 176 lv_obj_t * const * container) 177 { 178 lv_fragment_t * top = lv_fragment_manager_find_by_container(manager, *container); 179 if(top != NULL) { 180 lv_fragment_manager_remove(manager, top); 181 } 182 lv_fragment_manager_add(manager, fragment, container); 183 } 184 185 bool lv_fragment_manager_send_event(lv_fragment_manager_t * manager, int code, void * userdata) 186 { 187 LV_ASSERT_NULL(manager); 188 lv_fragment_stack_item_t * top = _lv_ll_get_tail(&manager->stack); 189 if(!top) return false; 190 lv_fragment_managed_states_t * states = top->states; 191 lv_fragment_t * instance = states->instance; 192 if(!instance) return false; 193 if(lv_fragment_manager_send_event(instance->child_manager, code, userdata)) return true; 194 if(!states->cls->event_cb) return false; 195 return states->cls->event_cb(instance, code, userdata); 196 } 197 198 size_t lv_fragment_manager_get_stack_size(lv_fragment_manager_t * manager) 199 { 200 LV_ASSERT_NULL(manager); 201 return _lv_ll_get_len(&manager->stack); 202 } 203 204 lv_fragment_t * lv_fragment_manager_get_top(lv_fragment_manager_t * manager) 205 { 206 LV_ASSERT(manager); 207 lv_fragment_stack_item_t * top = _lv_ll_get_tail(&manager->stack); 208 if(!top)return NULL; 209 return top->states->instance; 210 } 211 212 lv_fragment_t * lv_fragment_manager_find_by_container(lv_fragment_manager_t * manager, const lv_obj_t * container) 213 { 214 LV_ASSERT(manager); 215 lv_fragment_managed_states_t * states; 216 _LV_LL_READ(&manager->attached, states) { 217 if(*states->container == container) return states->instance; 218 } 219 return NULL; 220 } 221 222 lv_fragment_t * lv_fragment_manager_get_parent_fragment(lv_fragment_manager_t * manager) 223 { 224 LV_ASSERT_NULL(manager); 225 return manager->parent; 226 } 227 228 /********************** 229 * STATIC FUNCTIONS 230 **********************/ 231 232 static void item_create_obj(lv_fragment_managed_states_t * item) 233 { 234 LV_ASSERT(item->instance); 235 lv_fragment_create_obj(item->instance, item->container ? *item->container : NULL); 236 } 237 238 static void item_del_obj(lv_fragment_managed_states_t * item) 239 { 240 lv_fragment_del_obj(item->instance); 241 } 242 243 /** 244 * Detach, then destroy fragment 245 * @param item fragment states 246 */ 247 static void item_del_fragment(lv_fragment_managed_states_t * item) 248 { 249 lv_fragment_t * instance = item->instance; 250 if(instance->cls->detached_cb) { 251 instance->cls->detached_cb(instance); 252 } 253 instance->managed = NULL; 254 lv_fragment_del(instance); 255 item->instance = NULL; 256 } 257 258 259 static lv_fragment_managed_states_t * fragment_attach(lv_fragment_manager_t * manager, lv_fragment_t * fragment, 260 lv_obj_t * const * container) 261 { 262 LV_ASSERT(manager); 263 LV_ASSERT(fragment); 264 LV_ASSERT(fragment->managed == NULL); 265 lv_fragment_managed_states_t * item = _lv_ll_ins_tail(&manager->attached); 266 lv_memset_00(item, sizeof(lv_fragment_managed_states_t)); 267 item->cls = fragment->cls; 268 item->manager = manager; 269 item->container = container; 270 item->instance = fragment; 271 fragment->managed = item; 272 if(fragment->cls->attached_cb) { 273 fragment->cls->attached_cb(fragment); 274 } 275 return item; 276 } 277 278 #endif /*LV_USE_FRAGMENT*/