diff options
author | Marcel Hollerbach <mail@marcel-hollerbach.de> | 2019-09-03 10:12:19 +0200 |
---|---|---|
committer | Marcel Hollerbach <mail@marcel-hollerbach.de> | 2019-09-03 15:03:14 +0200 |
commit | 33544c0213b15dba1b7727d7293bbfd00781c1a0 (patch) | |
tree | c4dc15430cad02577038ebe7d7fd6bc84b582a7e | |
parent | 1e967b3c830cf04a413bdfeb7651338cf20a9aa2 (diff) | |
download | efl-33544c0213b15dba1b7727d7293bbfd00781c1a0.tar.gz |
collection view fixes
Co-authored-by: Mike Blumenkrantz <zmike@samsung.com>
-rw-r--r-- | src/lib/elementary/efl_ui_collection_view.c | 558 |
1 files changed, 418 insertions, 140 deletions
diff --git a/src/lib/elementary/efl_ui_collection_view.c b/src/lib/elementary/efl_ui_collection_view.c index 731a4e2431..95cec93a0e 100644 --- a/src/lib/elementary/efl_ui_collection_view.c +++ b/src/lib/elementary/efl_ui_collection_view.c @@ -51,6 +51,8 @@ struct _Efl_Ui_Collection_Request uint64_t length; Eina_Bool model_requested : 1; + Eina_Bool model_fetched : 1; + Eina_Bool need_entity : 1; Eina_Bool entity_requested : 1; }; @@ -63,7 +65,7 @@ struct _Efl_Ui_Collection_View_Data Efl_Gfx_Entity *sizer; Efl_Model *model; - Efl_Ui_Collection_Viewport *viewport[3]; + //Efl_Ui_Collection_Viewport *viewport[3]; Eina_Rbtree *cache; Eina_List *requests; // Array of Efl_Ui_Collection_Request in progress @@ -81,6 +83,8 @@ struct _Efl_Ui_Collection_View_Data Eina_Bool w : 1; Eina_Bool h : 1; } match_content; + + Efl_Ui_Position_Manager_Request_Range current_range, running_range; }; struct _Efl_Ui_Collection_View_Focus_Manager_Data @@ -96,6 +100,8 @@ static const char *COLLECTION_VIEW_MANAGED_YES = "yes"; #define MY_DATA_GET(obj, pd) \ Efl_Ui_Collection_View_Data *pd = efl_data_scope_get(obj, MY_CLASS); +static void _entity_request(Efl_Ui_Collection_View *obj, Efl_Ui_Collection_Request *request); + static int _cache_tree_lookup(const Eina_Rbtree *node, const void *key, int length EINA_UNUSED, void *data EINA_UNUSED) @@ -103,7 +109,11 @@ _cache_tree_lookup(const Eina_Rbtree *node, const void *key, const Efl_Ui_Collection_Item_Lookup *n = (Efl_Ui_Collection_Item_Lookup *)node; const uint64_t *index = key; - return n->index - *index; + if (n->index > *index) + return 1; + if (n->index < *index) + return -1; + return 0; } static Eina_Rbtree_Direction @@ -150,10 +160,10 @@ _all_cleanup(Efl_Ui_Collection_View_Data *pd) { Efl_Ui_Collection_Request *request; Eina_List *l, *ll; - unsigned int i; + //unsigned int i; _cache_cleanup(pd); - for (i = 0; i < 3; i++) + /*for (i = 0; i < 3; i++) { unsigned int j; @@ -161,7 +171,7 @@ _all_cleanup(Efl_Ui_Collection_View_Data *pd) for (j = 0; j < pd->viewport[i]->count; j++) _item_cleanup(pd->factory, &(pd->viewport[i]->items[j])); - } + }*/ EINA_LIST_FOREACH_SAFE(pd->requests, l, ll, request) eina_future_cancel(request->f); @@ -173,6 +183,8 @@ _size_from_model(Efl_Model *model, Eina_Size2D *r, const char *width, const char Eina_Value *vw, *vh; Eina_Bool success = EINA_FALSE; + EINA_SAFETY_ON_NULL_RETURN_VAL(model, EINA_FALSE); + vw = efl_model_property_get(model, width); vh = efl_model_property_get(model, height); @@ -218,12 +230,13 @@ _request_add(Eina_List *requests, Efl_Ui_Collection_Request **request, if ((*request)->offset + (*request)->length == index) { - if (need_entity) (*request)->entity_requested = EINA_TRUE; + if (need_entity) (*request)->need_entity = EINA_TRUE; (*request)->length += 1; + if ((*request)->length < 1) CRI("ACK"); return requests; } - requests = eina_list_append(requests, request); + requests = eina_list_append(requests, *request); create: *request = calloc(1, sizeof (Efl_Ui_Collection_Request)); @@ -232,7 +245,8 @@ _request_add(Eina_List *requests, Efl_Ui_Collection_Request **request, (*request)->length = 1; // At this point, we rely on the model caching ability to avoid recreating model (*request)->model_requested = EINA_TRUE; - (*request)->entity_requested = !!need_entity; + printf("MODEL REQ(%lu) %d\n", index, __LINE__); + (*request)->need_entity = !!need_entity; return requests; } @@ -244,13 +258,14 @@ _model_fetched_cb(Eo *obj, void *data, const Eina_Value v) Efl_Ui_Collection_Request *request = data; Efl_Model *child; unsigned int i, len; - +printf("MODEL FETCHED %d -> %d\n", request->offset, request->length); + request->model_fetched = EINA_TRUE; EINA_VALUE_ARRAY_FOREACH(&v, len, i, child) { Efl_Ui_Collection_Item_Lookup *insert; - unsigned int v; + //unsigned int v; - for (v = 0; v < 3; ++v) + /*for (v = 0; v < 3; ++v) { if (!pd->viewport[v]) continue; @@ -259,22 +274,44 @@ _model_fetched_cb(Eo *obj, void *data, const Eina_Value v) { uint64_t index = request->offset + i - pd->viewport[v]->offset; +if (!index) + printf("MODEL SET %d\n", v); efl_replace(&pd->viewport[v]->items[index].model, child); child = NULL; break; } - } + }*/ // When requesting a model, it should not be in the cache prior to the request if (!child) continue; - insert = calloc(1, sizeof (Efl_Ui_Collection_Item_Lookup)); - if (!insert) continue; + uint64_t search_index = request->offset + i; - insert->index = request->offset + i; - insert->item.model = efl_ref(child); + insert = (void*) eina_rbtree_inline_lookup(pd->cache, &search_index, + sizeof (search_index), _cache_tree_lookup, + NULL); + if (insert) + { + if (!insert->item.entity && request->need_entity) + { + //drop the old model here, overwrite with model + view + efl_unref(insert->item.model); + insert->item.model = efl_ref(child); + } + else + ERR("Inserting a model that was already fetched, dropping new model %d", search_index); + + } + else + { + insert = calloc(1, sizeof (Efl_Ui_Collection_Item_Lookup)); + if (!insert) continue; + insert->index = request->offset + i; + insert->item.model = efl_ref(child); + pd->cache = eina_rbtree_inline_insert(pd->cache, EINA_RBTREE_GET(insert), _cache_tree_cmp, NULL); + printf("INSERTING %lu\n", insert->index); + } - pd->cache = eina_rbtree_inline_insert(pd->cache, EINA_RBTREE_GET(insert), _cache_tree_cmp, NULL); } return v; @@ -286,9 +323,16 @@ _model_free_cb(Eo *o, void *data, const Eina_Future *dead_future EINA_UNUSED) MY_DATA_GET(o, pd); Efl_Ui_Collection_Request *request = data; - if (request->entity_requested) return; - pd->requests = eina_list_remove(pd->requests, request); - free(request); + if (request->need_entity) + { + if (!request->entity_requested) + _entity_request(o, request); + } + else + { + pd->requests = eina_list_remove(pd->requests, request); + free(request); + } } static Eina_Value @@ -319,13 +363,35 @@ _entity_propagate(Efl_Model *model, Efl_Gfx_Entity *entity) { Eina_Size2D item_size; - if (ITEM_SIZE_FROM_MODEL(model, item_size)) return EINA_FALSE; + if (!ITEM_SIZE_FROM_MODEL(model, item_size)) + { + if (!ITEM_BASE_SIZE_FROM_MODEL(efl_parent_get(model), item_size)) + return EINA_FALSE; + } - item_size = efl_gfx_hint_size_min_get(entity); + item_size = efl_gfx_hint_size_combined_min_get(entity); _size_to_model(model, item_size); return EINA_TRUE; } +static void +_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + printf("DEL0 %p\n", obj); +} + +static void +_hide(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + printf("HIDE0 %p\n", obj); +} + +static void +_show(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + printf("SHOW0 %p\n", obj); +} + static Eina_Value _entity_fetched_cb(Eo *obj, void *data, const Eina_Value v) { @@ -335,16 +401,26 @@ _entity_fetched_cb(Eo *obj, void *data, const Eina_Value v) unsigned int i, len; uint64_t updated_start_id; Eina_Bool updated = EINA_FALSE; - +printf("ENTITY FETCHED %d -> %d\n", request->offset, request->length); EINA_VALUE_ARRAY_FOREACH(&v, len, i, child) { Efl_Ui_Collection_Item_Lookup *lookup; uint64_t search_index; - unsigned int v; + //unsigned int v; efl_key_data_set(child, COLLECTION_VIEW_MANAGED, COLLECTION_VIEW_MANAGED_YES); + /* fix eventing in scroller by ensuring collection items are in the scroller hierarchy */ + efl_canvas_group_member_add(pd->pan, child); + efl_gfx_entity_visible_set(child, EINA_FALSE); + if (request->offset + i == 0) + { + printf("NEW0 %p\n", child); + evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _del, NULL); + evas_object_event_callback_add(child, EVAS_CALLBACK_HIDE, _hide, NULL); + evas_object_event_callback_add(child, EVAS_CALLBACK_SHOW, _show, NULL); + } - for (v = 0; v < 3; ++v) +/* for (v = 0; v < 3; ++v) { if (!pd->viewport[v]) continue; @@ -353,7 +429,20 @@ _entity_fetched_cb(Eo *obj, void *data, const Eina_Value v) { uint64_t index = request->offset + i - pd->viewport[v]->offset; + if (pd->viewport[v]->items[index].entity) + { + ERR("Entity already existing for id %d", i); + efl_unref(pd->viewport[v]->items[index].entity); + efl_del(pd->viewport[v]->items[index].entity); + pd->viewport[v]->items[index].entity = NULL; + } + efl_replace(&pd->viewport[v]->items[index].entity, child); +if (!pd->viewport[v]->items[index].model) + { + printf("OFFSET %u\n", pd->viewport[v]->offset); + CRI("ACK"); + } if (_entity_propagate(pd->viewport[v]->items[index].model, child)) { if (!updated) @@ -375,7 +464,7 @@ _entity_fetched_cb(Eo *obj, void *data, const Eina_Value v) child = NULL; break; } - } + }*/ // When requesting an entity, the model should already be in the cache if (!child) continue; @@ -386,7 +475,18 @@ _entity_fetched_cb(Eo *obj, void *data, const Eina_Value v) sizeof (search_index), _cache_tree_lookup, NULL); - if (!lookup) continue; + if (!lookup) + { + efl_ui_factory_release(pd->factory, child); + continue; + } + if (lookup->item.entity) + { + ERR("Entity already existing for id %lu", search_index); + efl_unref(lookup->item.entity); + efl_del(lookup->item.entity); + lookup->item.entity = NULL; + } lookup->item.entity = efl_ref(child); @@ -409,7 +509,14 @@ _entity_fetched_cb(Eo *obj, void *data, const Eina_Value v) } } } - + //flush out the update to the items, in case we have updated anything but not flushed yet. + if (updated) + { + efl_ui_position_manager_entity_item_size_changed(pd->manager, + updated_start_id, + i - 1); + updated = EINA_FALSE; + } return v; } @@ -427,12 +534,12 @@ static Eina_List * _cache_size_fetch(Eina_List *requests, Efl_Ui_Collection_Request **request, Efl_Ui_Collection_View_Data *pd, uint64_t search_index, - Efl_Ui_Position_Manager_Batch_Size_Access *target, + Efl_Ui_Position_Manager_Size_Batch_Entity *target, Eina_Size2D item_base) { Efl_Ui_Collection_Item_Lookup *lookup; Efl_Model *model; - Eina_Size2D item_size; + Eina_Size2D item_size = item_base; if (!pd->cache) goto not_found; @@ -447,24 +554,26 @@ _cache_size_fetch(Eina_List *requests, Efl_Ui_Collection_Request **request, // If we do not know the size if (!ITEM_SIZE_FROM_MODEL(model, item_size)) { - // But can calculate it now - if (!lookup->item.entity) goto not_found; - - item_size = efl_gfx_hint_size_min_get(lookup->item.entity); - _size_to_model(model, item_size); + item_size = efl_gfx_hint_size_combined_min_get(lookup->item.entity); + if (item_size.h == 0 && item_size.w == 0) + ITEM_BASE_SIZE_FROM_MODEL(pd->model, item_size); + else + _size_to_model(model, item_size); } target->size = item_size; - target->group = EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_NO_GROUP; - + target->element_depth = 0; + target->depth_leader = EINA_FALSE; + if (!item_size.w || !item_size.h) ERR("NULL SIZE ENT"); return requests; not_found: requests = _request_add(requests, request, search_index, EINA_FALSE); - target->size = item_base; - target->group = EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_NO_GROUP; - + target->size = item_size; + target->element_depth = 0; + target->depth_leader = EINA_FALSE; + if (!item_size.w || !item_size.h) ERR("NULL SIZE ENT"); return requests; } @@ -472,7 +581,7 @@ static Eina_List * _cache_entity_fetch(Eina_List *requests, Efl_Ui_Collection_Request **request, Efl_Ui_Collection_View_Data *pd, uint64_t search_index, - Efl_Ui_Position_Manager_Batch_Entity_Access *target) + Efl_Ui_Position_Manager_Object_Batch_Entity *target) { Efl_Ui_Collection_Item_Lookup *lookup; @@ -485,15 +594,18 @@ _cache_entity_fetch(Eina_List *requests, Efl_Ui_Collection_Request **request, if (!lookup->item.entity) goto not_found; target->entity = lookup->item.entity; - target->group = EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_NO_GROUP; + target->element_depth = 0; + target->depth_leader = EINA_FALSE; return requests; not_found: +// printf("LINE %d\n", __LINE__); requests = _request_add(requests, request, search_index, EINA_TRUE); target->entity = NULL; - target->group = EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_NO_GROUP; + target->element_depth = 0; + target->depth_leader = EINA_FALSE; return requests; } @@ -501,6 +613,8 @@ _cache_entity_fetch(Eina_List *requests, Efl_Ui_Collection_Request **request, static void _entity_request(Efl_Ui_Collection_View *obj, Efl_Ui_Collection_Request *request) { + if (request->model_requested && (!request->model_fetched)) return; + printf("ENTITY REQ %d -> %d\n", request->offset, request->length); request->f = efl_future_then(obj, request->f, .success_type = EINA_VALUE_TYPE_ARRAY, .success = _entity_fetch_cb); @@ -509,6 +623,7 @@ _entity_request(Efl_Ui_Collection_View *obj, Efl_Ui_Collection_Request *request) .success = _entity_fetched_cb, .data = request, .free = _entity_free_cb); + request->entity_requested = EINA_TRUE; } static inline void @@ -516,11 +631,10 @@ _entity_inflight_request(Efl_Ui_Collection_View *obj, Efl_Ui_Collection_Request *request, Efl_Ui_Collection_Request *inflight) { - if (request->entity_requested == EINA_FALSE) return ; - if (request->entity_requested == inflight->entity_requested) return ; + if (request->need_entity == EINA_FALSE) return ; + if (inflight->entity_requested) return ; _entity_request(obj, inflight); - inflight->entity_requested = EINA_TRUE; } static Eina_List * @@ -529,14 +643,16 @@ _batch_request_flush(Eina_List *requests, Efl_Ui_Collection_View_Data *pd) { Efl_Ui_Collection_Request *request; + Eina_List *ll, *next_list_item; - EINA_LIST_FREE(requests, request) + EINA_LIST_FOREACH_SAFE(requests, ll, next_list_item, request) { // Check request intersection with all pending request Efl_Ui_Collection_Request *inflight; Efl_Model *model; Eina_List *l; +if (request->length < 1) CRI("ACK"); EINA_LIST_FOREACH(pd->requests, l, inflight) { uint64_t istart = inflight->offset; @@ -550,11 +666,12 @@ _batch_request_flush(Eina_List *requests, if (rstart >= iend) continue; // request included in current inflight request - if (rstart >= istart && rend < iend) + if (rstart >= istart && rend <= iend) { _entity_inflight_request(obj, request, inflight); // In this case no need to start a request + requests = eina_list_remove_list(requests, ll); free(request); request = NULL; break; @@ -571,30 +688,34 @@ _batch_request_flush(Eina_List *requests, rn->offset = iend; rn->length = rend - iend; + if (rn->length < 1) CRI("ACK"); rn->model_requested = request->model_requested; - rn->entity_requested = request->entity_requested; + printf("MODEL REQ(%lu) %d\n", rn->offset, __LINE__); + rn->need_entity = request->need_entity; requests = eina_list_append(requests, rn); request->length = istart - rstart; + if (request->length < 1) CRI("ACK"); _entity_inflight_request(obj, request, inflight); - continue; } // request overflow left - if (rstart < istart && iend > istart && rend < iend) + if (rstart < istart && rend > istart && rend <= iend) { request->length = istart - rstart; + if (request->length < 1) CRI("ACK"); _entity_inflight_request(obj, request, inflight); continue; } // request overflow right - if (rstart >= istart && rstart < rend && iend < rend) + if (rstart >= istart && rstart < iend && iend <= rend) { request->offset = iend; request->length = rend - iend; + if (request->length < 1) CRI("ACK"); _entity_inflight_request(obj, request, inflight); continue; } @@ -606,12 +727,14 @@ _batch_request_flush(Eina_List *requests, // Are we ready yet if (!model) { + requests = eina_list_remove_list(requests, ll); free(request); continue; } // Is the request inside the limit of the model? if (request->offset >= efl_model_children_count_get(model)) { + requests = eina_list_remove_list(requests, ll); free(request); continue; } @@ -619,38 +742,37 @@ _batch_request_flush(Eina_List *requests, if (request->offset + request->length >= efl_model_children_count_get(model)) { request->length = efl_model_children_count_get(model) - request->offset; + if (request->length < 1) CRI("ACK"); } + if (!request->length) CRI("ACK"); // We now have a request, time to trigger a fetch // We assume here that we are always fetching the model (model_requested must be true) if (!request->model_requested) { - ERR("Someone forgot to set model_requested for %lu to %lu.", + CRI("Someone forgot to set model_requested for %lu to %lu.", request->offset, request->offset + request->length); request->model_requested = EINA_TRUE; } + printf("MODEL REQ FLUSH %lu -> %lu\n", request->offset, request->length); request->f = efl_model_children_slice_get(model, request->offset, request->length); request->f = efl_future_then(obj, request->f, .success = _model_fetched_cb, .data = request, .free = _model_free_cb); - if (request->entity_requested) - _entity_request(obj, request); - - pd->requests = eina_list_append(pd->requests, request); + eina_list_move_list(&pd->requests, &requests, ll); } - return NULL; } -static Efl_Ui_Position_Manager_Batch_Result -_batch_size_cb(void *data, int start_id, Eina_Rw_Slice memory) +static Efl_Ui_Position_Manager_Size_Batch_Result +_batch_size_cb(void *data, Efl_Ui_Position_Manager_Size_Call_Config conf, Eina_Rw_Slice memory) { MY_DATA_GET(data, pd); - Efl_Ui_Position_Manager_Batch_Size_Access *sizes; + Efl_Ui_Position_Manager_Size_Batch_Entity *sizes; Efl_Ui_Collection_Request *request = NULL; - Efl_Ui_Position_Manager_Batch_Result result = {-1, 0}; + Efl_Ui_Position_Manager_Size_Batch_Result result = {0}; Efl_Model *parent; Eina_List *requests = NULL; Eina_Size2D item_base; @@ -668,18 +790,19 @@ _batch_size_cb(void *data, int start_id, Eina_Rw_Slice memory) sizes = memory.mem; count = efl_model_children_count_get(parent); - limit = MIN(count - start_id, memory.len); + limit = conf.range.end_id - conf.range.start_id; +// printf("batch_size %u, %d\n", limit, start_id); // Look in the temporary cache now for the beginning of the buffer - if (pd->viewport[0] && ((uint64_t)(start_id + idx) < pd->viewport[0]->offset)) + /* if (pd->viewport[0] && ((uint64_t)(conf.range.start_id + idx) < pd->viewport[0]->offset)) { - while ((uint64_t)(start_id + idx) < pd->viewport[0]->offset) + while ((uint64_t)(conf.range.start_id + idx) < pd->viewport[0]->offset && idx < limit) { - uint64_t search_index = start_id + idx; - + uint64_t search_index = conf.range.start_id + idx; +// printf("LINE %d\n", __LINE__); requests = _cache_size_fetch(requests, &request, pd, search_index, &sizes[idx], item_base); - + if (!sizes[idx].size.w || !sizes[idx].size.h) ERR("NULL SIZE ENT"); idx++; } } @@ -690,15 +813,15 @@ _batch_size_cb(void *data, int start_id, Eina_Rw_Slice memory) if (!pd->viewport[i]) continue; while (idx < limit && - (pd->viewport[i]->offset <= start_id + idx) && - (start_id + idx < (pd->viewport[i]->offset + pd->viewport[i]->count))) + (pd->viewport[i]->offset <= conf.range.start_id + idx) && + (conf.range.start_id + idx < (pd->viewport[i]->offset + pd->viewport[i]->count))) { - uint16_t offset = start_id + idx - pd->viewport[i]->offset; + uint64_t offset = conf.range.start_id + idx - pd->viewport[i]->offset; Efl_Model *model = pd->viewport[i]->items[offset].model; Efl_Gfx_Entity *entity = pd->viewport[i]->items[offset].entity; Eina_Bool entity_request = EINA_FALSE; - if (!model) + if (model) { Eina_Size2D item_size; Eina_Bool found = EINA_FALSE; @@ -707,29 +830,44 @@ _batch_size_cb(void *data, int start_id, Eina_Rw_Slice memory) found = EINA_TRUE; if (!found && entity) { - item_size = efl_gfx_hint_size_min_get(entity); - _size_to_model(model, item_size); - found = EINA_TRUE; + item_size = efl_gfx_hint_size_combined_min_get(entity); + //if the size is 0 here, then we are running into trouble, + //fetch size from the parent model, where some fallback is defined + if (item_size.h == 0 && item_size.w == 0) + { + ITEM_BASE_SIZE_FROM_MODEL(pd->model, item_size); + found = EINA_TRUE; + } + else + { + _size_to_model(model, item_size); + found = EINA_TRUE; + } + } if (found) { sizes[idx].size = item_size; - sizes[idx].group = EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_NO_GROUP; + sizes[idx].element_depth = 0; + sizes[idx].depth_leader = EINA_FALSE; + if (!sizes[idx].size.w || !sizes[idx].size.h) ERR("NULL SIZE ENT"); goto done; } // We will need an entity to calculate this size entity_request = EINA_TRUE; } - +// printf("LINE %d\n", __LINE__); // No data, add to the requests - requests = _request_add(requests, &request, start_id + idx, entity_request); + requests = _request_add(requests, &request, conf.range.start_id + idx, entity_request); sizes[idx].size = item_base; - sizes[idx].group = EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_NO_GROUP; + sizes[idx].element_depth = 0; + sizes[idx].depth_leader = EINA_FALSE; done: + if (!sizes[idx].size.w || !sizes[idx].size.h) ERR("NULL SIZE ENT"); idx++; } } @@ -737,18 +875,43 @@ _batch_size_cb(void *data, int start_id, Eina_Rw_Slice memory) // Look in the temporary cache now for the end of the buffer while (idx < limit) { - uint64_t search_index = start_id + idx; - + uint64_t search_index = conf.range.start_id + idx; +// printf("%lu LINE %d\n", search_index, __LINE__); requests = _cache_size_fetch(requests, &request, pd, search_index, &sizes[idx], item_base); - + if (!sizes[idx].size.w || !sizes[idx].size.h) ERR("NULL SIZE ENT"); idx++; + }*/ + if (conf.cache_request) + { + printf("CACHING SIZE CALL\n"); + while (idx < limit) + { + sizes[idx].depth_leader = EINA_FALSE; + sizes[idx].element_depth = 0; + sizes[idx].size = item_base; + if (!sizes[idx].size.w || !sizes[idx].size.h) ERR("NULL SIZE ENT"); + idx++; + } } + else + { + while (idx < limit) + { + uint64_t search_index = conf.range.start_id + idx; + // printf("%lu LINE %d\n", search_index, __LINE__); + requests = _cache_size_fetch(requests, &request, pd, + search_index, &sizes[idx], item_base); + if (!sizes[idx].size.w || !sizes[idx].size.h) ERR("NULL SIZE ENT"); + idx++; + } - // Done, but flush request first - if (request) requests = eina_list_append(requests, request); - requests = _batch_request_flush(requests, data, pd); + // Done, but flush request first + if (request) requests = eina_list_append(requests, request); + + requests = _batch_request_flush(requests, data, pd); + } // Get the amount of filled item result.filled_items = limit; @@ -756,13 +919,13 @@ _batch_size_cb(void *data, int start_id, Eina_Rw_Slice memory) return result; } -static Efl_Ui_Position_Manager_Batch_Result -_batch_entity_cb(void *data, int start_id, Eina_Rw_Slice memory) +static Efl_Ui_Position_Manager_Object_Batch_Result +_batch_entity_cb(void *data, Efl_Ui_Position_Manager_Request_Range range, Eina_Rw_Slice memory) { MY_DATA_GET(data, pd); - Efl_Ui_Position_Manager_Batch_Entity_Access *entities; + Efl_Ui_Position_Manager_Object_Batch_Entity *entities; Efl_Ui_Collection_Request *request = NULL; - Efl_Ui_Position_Manager_Batch_Result result = {-1, 0}; + Efl_Ui_Position_Manager_Object_Batch_Result result = {0}; Eina_List *requests = NULL; Efl_Model *parent; unsigned int i, count, limit; @@ -772,14 +935,14 @@ _batch_entity_cb(void *data, int start_id, Eina_Rw_Slice memory) entities = memory.mem; count = efl_model_children_count_get(parent); - limit = MIN(count - start_id, memory.len); + limit = range.end_id - range.start_id;; // Look in the temporary cache now for the beginning of the buffer - if (pd->viewport[0] && ((uint64_t)(start_id + idx) < pd->viewport[0]->offset)) + /*if (pd->viewport[0] && ((uint64_t)(range.start_id + idx) < pd->viewport[0]->offset)) { - while ((uint64_t)(start_id + idx) < pd->viewport[0]->offset) + while (idx < limit && (uint64_t)(range.start_id + idx) < pd->viewport[0]->offset) { - uint64_t search_index = start_id + idx; + uint64_t search_index = range.start_id + idx; requests = _cache_entity_fetch(requests, &request, pd, search_index, &entities[idx]); @@ -794,24 +957,27 @@ _batch_entity_cb(void *data, int start_id, Eina_Rw_Slice memory) if (!pd->viewport[i]) continue; while (idx < limit && - (pd->viewport[i]->offset <= start_id + idx) && - (start_id + idx < (pd->viewport[i]->offset + pd->viewport[i]->count))) + (pd->viewport[i]->offset <= range.start_id + idx) && + (range.start_id + idx < (pd->viewport[i]->offset + pd->viewport[i]->count))) { - uint16_t offset = start_id + idx - pd->viewport[i]->offset; + uint64_t offset = range.start_id + idx - pd->viewport[i]->offset; Efl_Gfx_Entity *entity = pd->viewport[i]->items[offset].entity; if (!entity) { +// printf("LINE %d\n", __LINE__); // No data, add to the requests - requests = _request_add(requests, &request, start_id + idx, EINA_TRUE); + requests = _request_add(requests, &request, range.start_id + idx, EINA_TRUE); entities[idx].entity = NULL; - entities[idx].group = EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_NO_GROUP; + entities[idx].depth_leader = EINA_FALSE; + entities[idx].element_depth = 0; } else { entities[idx].entity = entity; - entities[idx].group = EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_NO_GROUP; + entities[idx].depth_leader = EINA_FALSE; + entities[idx].element_depth = 0; } idx++; @@ -821,16 +987,28 @@ _batch_entity_cb(void *data, int start_id, Eina_Rw_Slice memory) // Look in the temporary cache now for the end of the buffer while (idx < limit) { - uint64_t search_index = start_id + idx; + uint64_t search_index = range.start_id + idx; requests = _cache_entity_fetch(requests, &request, pd, search_index, &entities[idx]); idx++; - } + }*/ + while (idx < limit) + { + uint64_t search_index = range.start_id + idx; + requests = _cache_entity_fetch(requests, &request, pd, + search_index, &entities[idx]); + + idx++; + } // Done, but flush request first - if (request) requests = eina_list_append(requests, request); + if (request) + { + if (request->length < 1) CRI("ACK"); + requests = eina_list_append(requests, request); + } requests = _batch_request_flush(requests, data, pd); @@ -857,7 +1035,7 @@ flush_min_size(Eo *obj, Efl_Ui_Collection_View_Data *pd) if (!pd->match_content.h) tmp.h = -1; - efl_gfx_hint_size_min_set(obj, tmp); + efl_gfx_hint_size_restricted_min_set(obj, tmp); } static void @@ -913,7 +1091,7 @@ _viewport_walk_fill(Eina_List *requests, check_entity: if (viewport->items[j].entity) continue ; - +// printf("LINE %d\n", __LINE__); requests = _request_add(requests, ¤t, index, EINA_TRUE); } @@ -924,12 +1102,85 @@ _viewport_walk_fill(Eina_List *requests, } static void +_remove_data(Eo *obj, Efl_Ui_Collection_View_Data *pd, uint64_t remove_index) +{ + Efl_Ui_Collection_Item_Lookup *lookup; + + lookup = (void*) eina_rbtree_inline_lookup(pd->cache, &remove_index, + sizeof (remove_index), _cache_tree_lookup, + NULL); + + if (!lookup) return; + + pd->cache = (void*) eina_rbtree_inline_remove(pd->cache, + EINA_RBTREE_GET(lookup), + _cache_tree_cmp, NULL); + _cache_item_free(EINA_RBTREE_GET(lookup), pd); + lookup = (void*) eina_rbtree_inline_lookup(pd->cache, &remove_index, + sizeof (remove_index), _cache_tree_lookup, + NULL); + + EINA_SAFETY_ON_TRUE_RETURN(!!lookup); +} + +//per idle we are killing off 2 items, one of before and one after the current range. +static void +_idle_cb(void *data, const Efl_Event *event EINA_UNUSED) +{ + MY_DATA_GET(data, pd); + Eina_Bool finished = EINA_TRUE; + + const unsigned int count = efl_model_children_count_get(pd->model); + const unsigned int length = pd->current_range.end_id - pd->current_range.start_id; + const unsigned int lower_end = MAX((long)pd->current_range.start_id - (long)length/2, 0); + const unsigned int upper_end = pd->current_range.end_id + length/2; + const unsigned int upper_end_idx = count - pd->running_range.end_id; + + if (pd->running_range.start_id < lower_end) + { + _remove_data(data, pd, pd->running_range.start_id); + pd->running_range.start_id ++; + finished = EINA_FALSE; + } + + if (upper_end_idx > upper_end) + { + _remove_data(data, pd, upper_end_idx); + pd->running_range.end_id ++; + finished = EINA_FALSE; + } + + if (finished) + efl_event_callback_del(efl_main_loop_get(), EFL_LOOP_EVENT_IDLE, _idle_cb, data); +} + +static void +_manager_content_visible_range_changed_cb(void *data, const Efl_Event *ev) +{ + Efl_Ui_Position_Manager_Range_Update *event = ev->info; + MY_DATA_GET(data, pd); + + + printf("RANGE UPDATE %d %d\n", event->start_id, event->end_id); + + pd->current_range.start_id = event->start_id; + pd->current_range.end_id = event->end_id; + + pd->running_range.start_id = 0; + pd->running_range.end_id = 0; + + efl_event_callback_del(efl_main_loop_get(), EFL_LOOP_EVENT_IDLE, _idle_cb, data); + efl_event_callback_add(efl_main_loop_get(), EFL_LOOP_EVENT_IDLE, _idle_cb, data); +} + +#if 0 +static void _manager_content_visible_range_changed_cb(void *data, const Efl_Event *ev) { Efl_Ui_Position_Manager_Range_Update *event = ev->info; MY_DATA_GET(data, pd); Eina_List *requests = NULL; - unsigned int baseid; + long baseid; unsigned int delta, marginup, margindown; uint64_t upperlimit_offset, lowerlimit_offset; unsigned int i; @@ -942,17 +1193,17 @@ _manager_content_visible_range_changed_cb(void *data, const Efl_Event *ev) // First time setting up the viewport, so trigger request as we see fit if (!pd->viewport[0]) { - Eina_List *requests = NULL; - - baseid = (pd->start_id < delta) ? 0 : pd->start_id - delta; + baseid = pd->start_id - delta; for (i = 0; i < 3; i++) { pd->viewport[i] = calloc(1, sizeof (Efl_Ui_Collection_Viewport)); if (!pd->viewport[i]) continue; - pd->viewport[i]->offset = baseid + delta * i; + pd->viewport[i]->offset = MAX(baseid + delta * i, 0); + printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> OOOOFFFSET %d %lu\n", i, pd->viewport[i]->offset); pd->viewport[i]->count = delta; + printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> COUNT %d %d\n", i, pd->viewport[i]->count); pd->viewport[i]->items = calloc(delta, sizeof (Efl_Ui_Collection_Item)); if (!pd->viewport[i]->items) continue ; @@ -1023,6 +1274,8 @@ _manager_content_visible_range_changed_cb(void *data, const Efl_Event *ev) pd->viewport[i]->items = items[i]; pd->viewport[i]->count = delta; pd->viewport[i]->offset = pd->viewport[0]->offset + delta * i; + printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> OOOOFFFSET %d %lu\n", i, pd->viewport[i]->offset); + printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> COUNT %d %d\n", i, pd->viewport[i]->count); } } @@ -1052,8 +1305,9 @@ _manager_content_visible_range_changed_cb(void *data, const Efl_Event *ev) target = baseid; // cleanup before target - for (current = pd->viewport[0]->offset; current < target; current++) + for (current = pd->viewport[t]->offset; current < target; current++) { + if (!j) printf("MODEL CLEAR %d\n", t); _item_cleanup(pd->factory, &pd->viewport[t]->items[j]); j++; @@ -1113,6 +1367,8 @@ _manager_content_visible_range_changed_cb(void *data, const Efl_Event *ev) free(pd->viewport[i]->items); pd->viewport[i]->items = items[i]; pd->viewport[i]->offset = baseid + delta * i; + printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> OOOOFFFSET %d %lu\n", i, pd->viewport[i]->offset); + printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> COUNT %d %d\n", i, pd->viewport[i]->count); } } @@ -1128,8 +1384,10 @@ _manager_content_visible_range_changed_cb(void *data, const Efl_Event *ev) request->offset = lowerlimit_offset; // This length work over multiple viewport as they are contiguous request->length = lowerlimit_offset - pd->viewport[0]->offset; + if (request->length < 1) CRI("ACK"); request->model_requested = EINA_TRUE; - request->entity_requested = EINA_TRUE; +// printf("MODEL REQ(%lu) %d\n", request->offset, __LINE__); + request->need_entity = EINA_TRUE; requests = eina_list_append(requests, request); } @@ -1145,8 +1403,10 @@ _manager_content_visible_range_changed_cb(void *data, const Efl_Event *ev) request->offset = upperlimit_offset; // This length work over multiple viewport as they are contiguous request->length = pd->viewport[2]->offset + pd->viewport[2]->count - upperlimit_offset; + if (request->length < 1) CRI("ACK"); request->model_requested = EINA_TRUE; - request->entity_requested = EINA_TRUE; +// printf("MODEL REQ(%lu) %d\n", request->offset, __LINE__); + request->need_entity = EINA_TRUE; requests = eina_list_append(requests, request); } @@ -1155,6 +1415,8 @@ _manager_content_visible_range_changed_cb(void *data, const Efl_Event *ev) requests = _batch_request_flush(requests, data, pd); } +#endif + EFL_CALLBACKS_ARRAY_DEFINE(manager_cbs, { EFL_UI_POSITION_MANAGER_ENTITY_EVENT_CONTENT_SIZE_CHANGED, _manager_content_size_changed_cb }, { EFL_UI_POSITION_MANAGER_ENTITY_EVENT_CONTENT_MIN_SIZE_CHANGED, _manager_content_min_size_changed_cb }, @@ -1212,10 +1474,6 @@ _efl_ui_collection_view_position_manager_set(Eo *obj, Efl_Ui_Collection_View_Dat if (pd->manager) { efl_event_callback_array_del(pd->manager, manager_cbs(), obj); - efl_ui_position_manager_entity_data_access_set(pd->manager, - NULL, NULL, NULL, - NULL, NULL, NULL, - 0); efl_del(pd->manager); } pd->manager = manager; @@ -1227,11 +1485,18 @@ _efl_ui_collection_view_position_manager_set(Eo *obj, Efl_Ui_Collection_View_Dat efl_parent_set(pd->manager, obj); efl_event_callback_array_add(pd->manager, manager_cbs(), obj); - efl_ui_position_manager_entity_data_access_set(pd->manager, - efl_ref(obj), _batch_entity_cb, _batch_free_cb, - efl_ref(obj), _batch_size_cb, _batch_free_cb, - count); - efl_ui_position_manager_entity_viewport_set(pd->manager, efl_ui_scrollable_viewport_geometry_get(obj)); + switch(efl_ui_position_manager_entity_version(pd->manager, 1)) + { + case 1: + efl_ui_position_manager_data_access_v1_data_access_set(pd->manager, + efl_ref(obj), _batch_entity_cb, NULL, + efl_ref(obj), _batch_size_cb, NULL, + count); + break; + } + + if (efl_finalized_get(obj)) + efl_ui_position_manager_entity_viewport_set(pd->manager, efl_ui_scrollable_viewport_geometry_get(obj)); efl_ui_layout_orientation_set(pd->manager, pd->direction); } @@ -1270,7 +1535,7 @@ _efl_model_child_added(void *data, const Efl_Event *event) _cache_cleanup(pd); // Check if we really have something to do - if (!pd->viewport[0]) goto notify_manager; + /*if (!pd->viewport[0]) goto notify_manager; // Insert the child in the viewport if necessary for (i = 0; i < 3; i++) @@ -1311,14 +1576,15 @@ _efl_model_child_added(void *data, const Efl_Event *event) request->offset = ev->index; request->length = 1; request->model_requested = EINA_TRUE; - request->entity_requested = EINA_TRUE; +// printf("MODEL REQ(%lu) %d\n", request->offset, __LINE__); + request->need_entity = EINA_TRUE; requests = eina_list_append(requests, request); requests = _batch_request_flush(requests, data, pd); break; - } + }*/ notify_manager: efl_ui_position_manager_entity_item_added(pd->manager, ev->index, NULL); @@ -1335,7 +1601,7 @@ _efl_model_child_removed(void *data, const Efl_Event *event) _cache_cleanup(pd); // Check if we really have something to do - if (!pd->viewport[0]) goto notify_manager; + /*if (!pd->viewport[0]) goto notify_manager; // Insert the child in the viewport if necessary for (i = 0; i < 3; i++) @@ -1377,14 +1643,15 @@ _efl_model_child_removed(void *data, const Efl_Event *event) request->offset = pd->viewport[2]->offset + pd->viewport[i]->count - 1; request->length = 1; request->model_requested = EINA_TRUE; - request->entity_requested = EINA_TRUE; +// printf("MODEL REQ(%lu) %d\n", request->offset, __LINE__); + request->need_entity = EINA_TRUE; requests = eina_list_append(requests, request); requests = _batch_request_flush(requests, data, pd); break; - } + }*/ notify_manager: efl_ui_position_manager_entity_item_removed(pd->manager, ev->index, NULL); @@ -1441,12 +1708,17 @@ _efl_ui_collection_view_model_changed(void *data, const Efl_Event *event) efl_ui_view_model_set(efl_added, ev->current)); count = efl_model_children_count_get(model); - efl_ui_position_manager_entity_data_access_set(pd->manager, - efl_ref(data), _batch_entity_cb, _batch_free_cb, - efl_ref(data), _batch_size_cb, _batch_free_cb, - count); + switch(efl_ui_position_manager_entity_version(pd->manager, 1)) + { + case 1: + efl_ui_position_manager_data_access_v1_data_access_set(pd->manager, + efl_ref(data), _batch_entity_cb, NULL, + efl_ref(data), _batch_size_cb, NULL, + count); + break; + } - for (i = 0; i < 3; i++) + /*for (i = 0; i < 3; i++) { Efl_Ui_Collection_Request *request; @@ -1458,13 +1730,17 @@ _efl_ui_collection_view_model_changed(void *data, const Efl_Event *event) request->offset = pd->viewport[i]->offset; request->length = pd->viewport[i]->count; + if (request->length < 1) CRI("ACK"); request->model_requested = EINA_TRUE; - request->entity_requested = EINA_TRUE; +// printf("MODEL REQ(%lu) %d\n", request->offset, __LINE__); + request->need_entity = EINA_TRUE; requests = eina_list_append(requests, request); - } + }*/ requests = _batch_request_flush(requests, data, pd); + + pd->model = model; } static void @@ -1493,17 +1769,19 @@ _pan_position_changed_cb(void *data, const Efl_Event *ev EINA_UNUSED) } EFL_CALLBACKS_ARRAY_DEFINE(pan_events_cb, - {EFL_UI_PAN_EVENT_PAN_POSITION_CHANGED, _pan_position_changed_cb}, - {EFL_UI_PAN_EVENT_PAN_VIEWPORT_CHANGED, _pan_viewport_changed_cb}, + {EFL_UI_PAN_EVENT_PAN_CONTENT_POSITION_CHANGED, _pan_position_changed_cb}, + {EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _pan_viewport_changed_cb}, + {EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _pan_viewport_changed_cb}, ) static Efl_Object * _efl_ui_collection_view_efl_object_constructor(Eo *obj, Efl_Ui_Collection_View_Data *pd) { + pd->direction = EFL_UI_LAYOUT_ORIENTATION_VERTICAL; obj = efl_constructor(efl_super(obj, EFL_UI_COLLECTION_VIEW_CLASS)); if (!elm_widget_theme_klass_get(obj)) - elm_widget_theme_klass_set(obj, "collection"); + elm_widget_theme_klass_set(obj, "item_container"); efl_wref_add(efl_add(EFL_CANVAS_RECTANGLE_CLASS, evas_object_evas_get(obj)), &pd->sizer); efl_gfx_color_set(pd->sizer, 0, 0, 0, 0); @@ -1619,7 +1897,7 @@ _efl_ui_collection_view_efl_ui_focus_manager_move(Eo *obj, Efl_Ui_Collection_Vie new_obj = efl_ui_focus_manager_move(efl_super(obj, MY_CLASS), direction); focus = efl_ui_focus_manager_focus_get(obj); - step = efl_gfx_hint_size_min_get(focus); + step = efl_gfx_hint_size_combined_min_get(focus); if (!new_obj) { Eina_Rect pos = efl_gfx_entity_geometry_get(focus); @@ -1776,7 +2054,7 @@ _efl_ui_collection_view_focus_manager_efl_ui_focus_manager_request_move(Eo *obj, { unsigned int i; - for (i = 0; i < 3; i++) +/* for (i = 0; i < 3; i++) { if (!cpd->viewport[i]) continue; @@ -1788,7 +2066,7 @@ _efl_ui_collection_view_focus_manager_efl_ui_focus_manager_request_move(Eo *obj, // We shouldn't get in a case where the available item is NULL if (!new_item) break; // Just in case _assert_item_available(new_item, new_id, cpd); - } + }*/ } } else |