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*/