summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hollerbach <mail@marcel-hollerbach.de>2019-09-03 10:12:19 +0200
committerMarcel Hollerbach <mail@marcel-hollerbach.de>2019-09-03 15:03:14 +0200
commit33544c0213b15dba1b7727d7293bbfd00781c1a0 (patch)
treec4dc15430cad02577038ebe7d7fd6bc84b582a7e
parent1e967b3c830cf04a413bdfeb7651338cf20a9aa2 (diff)
downloadefl-33544c0213b15dba1b7727d7293bbfd00781c1a0.tar.gz
collection view fixes
Co-authored-by: Mike Blumenkrantz <zmike@samsung.com>
-rw-r--r--src/lib/elementary/efl_ui_collection_view.c558
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, &current, 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