From d98d434e56fe98af76cdccc38e96f0e8f34db590 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Tue, 30 Jul 2019 11:13:46 +0200 Subject: [PATCH] efl_ui_position_manager: move from accessor to function callback this commit enables access to the item structure of the collection via a function callback. The function callback now enables batching for items, which does not pay off right now. However, a few more optimizations can be done in order to get the whole payoff. Reviewed-by: Cedric BAIL Differential Revision: https://phab.enlightenment.org/D9445 --- src/lib/elementary/efl_ui_collection.c | 96 ++++++++++--------- .../efl_ui_position_manager_common.h | 48 ++++++++++ .../efl_ui_position_manager_entity.eo | 26 ++++- .../elementary/efl_ui_position_manager_grid.c | 70 +++++++------- .../elementary/efl_ui_position_manager_list.c | 72 ++++++++------ .../efl_ui_test_position_manager_common.c | 63 +++++------- 6 files changed, 230 insertions(+), 145 deletions(-) create mode 100644 src/lib/elementary/efl_ui_position_manager_common.h diff --git a/src/lib/elementary/efl_ui_collection.c b/src/lib/elementary/efl_ui_collection.c index efc56fc5c6..73ceabd939 100644 --- a/src/lib/elementary/efl_ui_collection.c +++ b/src/lib/elementary/efl_ui_collection.c @@ -13,21 +13,20 @@ #include "elm_priv.h" typedef struct { - Eina_Accessor acc; unsigned int last_index; const Eina_List *current; Eina_List **items; } Fast_Accessor; -static Eina_Bool -_fast_accessor_get_at(Fast_Accessor *accessor, unsigned int idx, void **data) +static const Eina_List* +_fast_accessor_get_at(Fast_Accessor *accessor, unsigned int idx) { const Eina_List *over; unsigned int middle; unsigned int i; if (idx >= eina_list_count(*accessor->items)) - return EINA_FALSE; + return NULL; if (accessor->last_index == idx) over = accessor->current; @@ -70,33 +69,12 @@ _fast_accessor_get_at(Fast_Accessor *accessor, unsigned int idx, void **data) } if (!over) - return EINA_FALSE; + return NULL; accessor->last_index = idx; accessor->current = over; - *data = eina_list_data_get(over); - return EINA_TRUE; -} - - -static Eina_Accessor* -_fast_accessor_clone(Fast_Accessor *accessor) -{ - return eina_list_accessor_new(*accessor->items); -} - -static Eina_List * -_fast_accessor_get_container(Fast_Accessor *accessor EINA_UNUSED) -{ - ERR("Not allowed to get a container!"); - return NULL; -} - -static void -_fast_accessor_free(Fast_Accessor *accessor EINA_UNUSED) -{ - ERR("Freeing this accessor is not supported"); + return over; } static void @@ -105,12 +83,6 @@ _fast_accessor_init(Fast_Accessor *accessor, Eina_List **items) //this is the accessor for accessing the items //we have to workarround here the problem that //no accessor can be created for a not yet created list. - accessor->acc.version = EINA_ACCESSOR_VERSION; - accessor->acc.get_at = FUNC_ACCESSOR_GET_AT(_fast_accessor_get_at); - accessor->acc.clone = FUNC_ACCESSOR_CLONE(_fast_accessor_clone); - accessor->acc.get_container = FUNC_ACCESSOR_GET_CONTAINER(_fast_accessor_get_container); - accessor->acc.free = FUNC_ACCESSOR_FREE(_fast_accessor_free); - EINA_MAGIC_SET(&accessor->acc, EINA_MAGIC_ACCESSOR); accessor->items = items; } @@ -285,22 +257,53 @@ _efl_ui_collection_selected_items_get(Eo *obj EINA_UNUSED, Efl_Ui_Collection_Dat return eina_list_iterator_new(pd->selected); } -static Eina_Bool -_size_accessor_get_at(Fast_Accessor *accessor, unsigned int idx, void **data) +static int +_size_accessor_get_at(void *data, int start_id, Eina_Rw_Slice memory) { - Eina_Bool res = EINA_FALSE; - Efl_Gfx_Entity *geom; - Eina_Size2D *size = (void*)data; + Fast_Accessor *accessor = data; + size_t i; + const Eina_List *lst = _fast_accessor_get_at(accessor, start_id); - res = _fast_accessor_get_at(accessor, idx,(void*) &geom); + EINA_SAFETY_ON_NULL_RETURN_VAL(lst, -1); - if (!res) return EINA_FALSE; + for (i = 0; i < memory.len; ++i) + { + Efl_Gfx_Entity *geom = eina_list_data_get(lst); + Eina_Size2D size = efl_gfx_hint_size_min_get(geom); - *size = efl_gfx_hint_size_min_get(geom); + ((Eina_Size2D*)memory.mem)[i] = size; + lst = eina_list_next(lst); + if (!lst) + { + i++; + break; + } + } - return res; + return i; } +static int +_obj_accessor_get_at(void *data, int start_id, Eina_Rw_Slice memory) +{ + Fast_Accessor *accessor = data; + size_t i; + const Eina_List *lst = _fast_accessor_get_at(accessor, start_id); + + for (i = 0; i < memory.len; ++i) + { + Efl_Gfx_Entity *geom = eina_list_data_get(lst); + + ((Efl_Gfx_Entity**)memory.mem)[i] = geom; + lst = eina_list_next(lst); + if (!lst) + { + i++; + break; + } + } + return i; +} EOLIAN static Efl_Object* _efl_ui_collection_efl_object_constructor(Eo *obj, Efl_Ui_Collection_Data *pd EINA_UNUSED) @@ -311,7 +314,6 @@ _efl_ui_collection_efl_object_constructor(Eo *obj, Efl_Ui_Collection_Data *pd EI _fast_accessor_init(&pd->obj_accessor, &pd->items); _fast_accessor_init(&pd->size_accessor, &pd->items); - pd->size_accessor.acc.get_at = FUNC_ACCESSOR_GET_AT(_size_accessor_get_at); if (!elm_widget_theme_klass_get(obj)) elm_widget_theme_klass_set(obj, "item_container"); @@ -759,7 +761,7 @@ _efl_ui_collection_position_manager_set(Eo *obj, Efl_Ui_Collection_Data *pd, Efl if (pd->pos_man) { efl_event_callback_array_del(pd->pos_man, pos_manager_cbs(), obj); - efl_ui_position_manager_entity_data_access_set(pd->pos_man, NULL, NULL, 0); + efl_ui_position_manager_entity_data_access_set(pd->pos_man, NULL, NULL, NULL, NULL, NULL, NULL, 0); efl_del(pd->pos_man); } pd->pos_man = layouter; @@ -767,7 +769,11 @@ _efl_ui_collection_position_manager_set(Eo *obj, Efl_Ui_Collection_Data *pd, Efl { efl_parent_set(pd->pos_man, obj); efl_event_callback_array_add(pd->pos_man, pos_manager_cbs(), obj); - efl_ui_position_manager_entity_data_access_set(pd->pos_man, &pd->obj_accessor.acc, &pd->size_accessor.acc, eina_list_count(pd->items)); + //efl_ui_position_manager_entity_data_access_set(pd->pos_man, &pd->obj_accessor.acc, &pd->size_accessor.acc, eina_list_count(pd->items)); + efl_ui_position_manager_entity_data_access_set(pd->pos_man, + &pd->obj_accessor, _obj_accessor_get_at, NULL, + &pd->size_accessor, _size_accessor_get_at, NULL, + eina_list_count(pd->items)); efl_ui_position_manager_entity_viewport_set(pd->pos_man, efl_ui_scrollable_viewport_geometry_get(obj)); efl_ui_layout_orientation_set(pd->pos_man, pd->dir); } diff --git a/src/lib/elementary/efl_ui_position_manager_common.h b/src/lib/elementary/efl_ui_position_manager_common.h new file mode 100644 index 0000000000..56c7eeef08 --- /dev/null +++ b/src/lib/elementary/efl_ui_position_manager_common.h @@ -0,0 +1,48 @@ +#ifndef EFL_UI_POSITION_MANAGER_COMMON_H +#define EFL_UI_POSITION_MANAGER_COMMON_H 1 + +#include +#include +#include "efl_ui_position_manager_entity.eo.h" + +typedef struct { + void *data; + Efl_Ui_Position_Manager_Batch_Access_Entity access; //this can also be the size accessor, but that does not matter here + Eina_Free_Cb free_cb; +} Api_Callback; + +static inline int +_fill_buffer(Api_Callback *cb , int start_id, int len, void *data) +{ + Eina_Rw_Slice slice; + slice.mem = data; + slice.len = len; + + return cb->access(cb->data, start_id, slice); +} + +static inline void +vis_change_segment(Api_Callback *cb, int a, int b, Eina_Bool flag) +{ + const int len = 50; + Efl_Gfx_Entity *data[len]; + + if (a == b) return; + + for (int i = MIN(a, b); i < MAX(a, b); ++i) + { + Efl_Gfx_Entity *ent = NULL; + int buffer_id = (i-MIN(a,b)) % len; + + if (buffer_id == 0) + { + EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(cb, MIN(a,b), len, data) >= 0); + } + ent = data[i - MIN(a,b)]; + if (ent && !efl_ui_focus_object_focus_get(ent)) + { + efl_gfx_entity_visible_set(ent, flag); + } + } +} +#endif diff --git a/src/lib/elementary/efl_ui_position_manager_entity.eo b/src/lib/elementary/efl_ui_position_manager_entity.eo index 471e5d6086..4a65572181 100644 --- a/src/lib/elementary/efl_ui_position_manager_entity.eo +++ b/src/lib/elementary/efl_ui_position_manager_entity.eo @@ -1,4 +1,22 @@ +function Efl.Ui.Position_Manager.Batch_Access_Entity { + [[ Function callback for getting a batch of items]] + params { + start_id : int; [[The id of the first item to fetch]] + memory : rw_slice; [[The slice to fill the information in, the full slice will be filled if there are enough items]] + } + return: int; [[The number of filled elements in the slice]] +}; + +function Efl.Ui.Position_Manager.Batch_Access_Size { + [[ Function callback for getting sizes of a batch of items]] + params { + start_id : int; [[The id of the first item to fetch]] + memory : rw_slice; [[The slice to fill the information in, the full slice will be filled if there are enough items]] + } + return: int; [[The number of filled elements in the slice]] +}; + interface @beta Efl.Ui.Position_Manager.Entity extends Efl.Ui.Layout_Orientable { [[ @@ -15,14 +33,16 @@ interface @beta Efl.Ui.Position_Manager.Entity extends Efl.Ui.Layout_Orientable $size_access gives access to the 2D sizes for the items to manage. All sizes will always be valid, and might change over time (indicated through the @.item_size_changed method). The whole range might need to be traversed in order to calculate the position of all items in some arrangements. + + You can access a batch of objects or sizes by calling the here passed function callbacks. Further details can be found at the function definitions. ]] set { } values { - obj_access : accessor; [[The accessor for canvas obejcts, even if the id is valid, the returned object may be NULL]] - size_access : accessor; [[Accessor for the size, returned values are always valid, but might be changed / updated]] - size : int; [[valid size for accessors, 0 <= i < size]] + obj_access : Efl.Ui.Position_Manager.Batch_Access_Entity; [[Function callback for canvas objects, even if the start_id is valid, the returned objects may be NULL]] + size_access : Efl.Ui.Position_Manager.Batch_Access_Size; [[Function callback for the size, returned values are always valid, but might be changed / updated]] + size : int; [[valid size for start_id, 0 <= i < size]] } } @property viewport { diff --git a/src/lib/elementary/efl_ui_position_manager_grid.c b/src/lib/elementary/efl_ui_position_manager_grid.c index 1ae249fca1..2de7ddf896 100644 --- a/src/lib/elementary/efl_ui_position_manager_grid.c +++ b/src/lib/elementary/efl_ui_position_manager_grid.c @@ -6,13 +6,14 @@ #include #include "elm_widget.h" #include "elm_priv.h" +#include "efl_ui_position_manager_common.h" #define MY_CLASS EFL_UI_POSITION_MANAGER_GRID_CLASS #define MY_DATA_GET(obj, pd) \ Efl_Ui_Position_Manager_Grid_Data *pd = efl_data_scope_get(obj, MY_CLASS); typedef struct { - Eina_Accessor *content_acc, *size_acc; + Api_Callback min_size, object; unsigned int size; Eina_Rect viewport; Eina_Vector2 scroll_position; @@ -29,27 +30,14 @@ typedef struct { } current_display_table; } Efl_Ui_Position_Manager_Grid_Data; -static inline void -vis_change_segment(Efl_Ui_Position_Manager_Grid_Data *pd, int a, int b, Eina_Bool flag) -{ - for (int i = MIN(a, b); i < MAX(a, b); ++i) - { - Efl_Gfx_Entity *ent; - - EINA_SAFETY_ON_FALSE_RETURN(eina_accessor_data_get(pd->content_acc, i, (void**) &ent)); - if (ent && !efl_ui_focus_object_focus_get(ent)) - { - efl_gfx_entity_visible_set(ent, flag); - } - } -} - static void _reposition_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd) { Eina_Size2D space_size; int relevant_space_size, relevant_viewport; unsigned int start_id, end_id, step; + const int len = 100; + Efl_Gfx_Entity *obj_buffer[len]; if (!pd->size) return; if (pd->max_min_size.w <= 0 || pd->max_min_size.h <= 0) return; @@ -83,22 +71,28 @@ _reposition_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd) { //it is important to first make the segment visible here, and then hide the rest //otherwise we get a state where item_container has 0 subchildren, which triggers a lot of focus logic. - vis_change_segment(pd, start_id, end_id, EINA_TRUE); - vis_change_segment(pd, pd->prev_run.start_id, pd->prev_run.end_id, EINA_FALSE); + vis_change_segment(&pd->object, start_id, end_id, EINA_TRUE); + vis_change_segment(&pd->object, pd->prev_run.start_id, pd->prev_run.end_id, EINA_FALSE); } else { - vis_change_segment(pd, pd->prev_run.start_id, start_id, (pd->prev_run.start_id > start_id)); - vis_change_segment(pd, pd->prev_run.end_id, end_id, (pd->prev_run.end_id < end_id)); + vis_change_segment(&pd->object, pd->prev_run.start_id, start_id, (pd->prev_run.start_id > start_id)); + vis_change_segment(&pd->object, pd->prev_run.end_id, end_id, (pd->prev_run.end_id < end_id)); } for (unsigned int i = start_id; i < end_id; ++i) { Eina_Rect geom; Efl_Gfx_Entity *ent; + int buffer_id = (i-start_id) % len; geom.size = pd->max_min_size; geom.pos = pd->viewport.pos; + if (buffer_id == 0) + { + EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->object, i, len, obj_buffer) > 0); + } + if (pd->dir == EFL_UI_LAYOUT_ORIENTATION_VERTICAL) { geom.x += pd->max_min_size.w*(i%pd->current_display_table.columns); @@ -112,7 +106,8 @@ _reposition_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd) geom.x -= (relevant_space_size); } - EINA_SAFETY_ON_FALSE_RETURN(eina_accessor_data_get(pd->content_acc, i, (void**) &ent)); + ent = ((Efl_Gfx_Entity**)obj_buffer)[buffer_id]; + //printf(">%d (%d, %d, %d, %d) %p\n", i, geom.x, geom.y, geom.w, geom.h, ent); efl_gfx_entity_geometry_set(ent, geom); } @@ -170,13 +165,10 @@ _flush_abs_size(Eo *obj, Efl_Ui_Position_Manager_Grid_Data *pd) } static inline void -_update_min_size(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd, int added_index) +_update_min_size(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd, int added_index EINA_UNUSED, Eina_Size2D min_size) { - Eina_Size2D elemsize; - - EINA_SAFETY_ON_FALSE_RETURN(eina_accessor_data_get(pd->size_acc, added_index, (void*)&elemsize)); - pd->max_min_size.w = MAX(pd->max_min_size.w, elemsize.w); - pd->max_min_size.h = MAX(pd->max_min_size.h, elemsize.h); + pd->max_min_size.w = MAX(pd->max_min_size.w, min_size.w); + pd->max_min_size.h = MAX(pd->max_min_size.h, min_size.h); } static inline void @@ -197,10 +189,14 @@ _flush_min_size(Eo *obj, Efl_Ui_Position_Manager_Grid_Data *pd) } EOLIAN static void -_efl_ui_position_manager_grid_efl_ui_position_manager_entity_data_access_set(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd, Eina_Accessor *obj_access, Eina_Accessor *size_access, int size) +_efl_ui_position_manager_grid_efl_ui_position_manager_entity_data_access_set(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd, void *obj_access_data, Efl_Ui_Position_Manager_Batch_Access_Entity obj_access, Eina_Free_Cb obj_access_free_cb, void *size_access_data, Efl_Ui_Position_Manager_Batch_Access_Size size_access, Eina_Free_Cb size_access_free_cb, int size) { - pd->size_acc = size_access; - pd->content_acc = obj_access; + pd->object.data = obj_access_data; + pd->object.access = obj_access; + pd->object.free_cb = obj_access_free_cb; + pd->min_size.data = size_access_data; + pd->min_size.access = size_access; + pd->min_size.free_cb = size_access_free_cb; pd->size = size; } @@ -223,10 +219,12 @@ _efl_ui_position_manager_grid_efl_ui_position_manager_entity_scroll_position_set EOLIAN static void _efl_ui_position_manager_grid_efl_ui_position_manager_entity_item_added(Eo *obj, Efl_Ui_Position_Manager_Grid_Data *pd, int added_index, Efl_Gfx_Entity *subobj EINA_UNUSED) { + Eina_Size2D size[1]; pd->size ++; efl_gfx_entity_visible_set(subobj, EINA_FALSE); - _update_min_size(obj, pd, added_index); + EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->min_size, added_index, 1, &size) == 1); + _update_min_size(obj, pd, added_index, size[0]); _flush_min_size(obj, pd); _flush_abs_size(obj, pd); _reposition_content(obj, pd); //FIXME we might can skip that @@ -249,9 +247,17 @@ _efl_ui_position_manager_grid_efl_ui_position_manager_entity_item_removed(Eo *ob EOLIAN static void _efl_ui_position_manager_grid_efl_ui_position_manager_entity_item_size_changed(Eo *obj, Efl_Ui_Position_Manager_Grid_Data *pd, int start_id, int end_id) { + const int len = 50; + Eina_Size2D data[len]; + for (int i = start_id; i <= end_id; ++i) { - _update_min_size(obj, pd, i); + int buffer_id = (i-start_id) % len; + if (buffer_id == 0) + { + EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->min_size, start_id, len, data) >= 0); + } + _update_min_size(obj, pd, i, data[i-start_id]); } _flush_min_size(obj, pd); diff --git a/src/lib/elementary/efl_ui_position_manager_list.c b/src/lib/elementary/efl_ui_position_manager_list.c index c793bd3327..4a8497b4bd 100644 --- a/src/lib/elementary/efl_ui_position_manager_list.c +++ b/src/lib/elementary/efl_ui_position_manager_list.c @@ -7,13 +7,14 @@ #include #include "elm_widget.h" #include "elm_priv.h" +#include "efl_ui_position_manager_common.h" #define MY_CLASS EFL_UI_POSITION_MANAGER_LIST_CLASS #define MY_DATA_GET(obj, pd) \ Efl_Ui_Position_Manager_List_Data *pd = efl_data_scope_get(obj, MY_CLASS); typedef struct { - Eina_Accessor *content_acc, *size_acc; + Api_Callback min_size, object; unsigned int size; Eina_Future *rebuild_absolut_size; Eina_Rect viewport; @@ -40,6 +41,9 @@ static void cache_require(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd) { unsigned int i; + const int len = 100; + Eina_Size2D size_buffer[100]; + if (pd->size_cache) return; @@ -59,8 +63,14 @@ cache_require(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd) Eina_Size2D size; int step; int min; + int buffer_id = i % len; + + if (buffer_id == 0) + { + EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->min_size, i, len, size_buffer) > 0); + } + size = size_buffer[buffer_id]; - eina_accessor_data_get(pd->size_acc, i, (void**) &size); if (pd->dir == EFL_UI_LAYOUT_ORIENTATION_VERTICAL) { step = size.h; @@ -122,21 +132,6 @@ recalc_absolut_size(Eo *obj, Efl_Ui_Position_Manager_List_Data *pd) efl_event_callback_call(obj, EFL_UI_POSITION_MANAGER_ENTITY_EVENT_CONTENT_MIN_SIZE_CHANGED, &min_size); } -static inline void -vis_change_segment(Efl_Ui_Position_Manager_List_Data *pd, int a, int b, Eina_Bool flag) -{ - for (int i = MIN(a, b); i < MAX(a, b); ++i) - { - Efl_Gfx_Entity *ent = NULL; - - eina_accessor_data_get(pd->content_acc, i, (void**) &ent); - if (ent && !efl_ui_focus_object_focus_get(ent)) - { - efl_gfx_entity_visible_set(ent, flag); - } - } -} - static void position_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd) { @@ -144,6 +139,9 @@ position_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd) Eina_Size2D space_size; unsigned int start_id = 0, end_id = 0, i; int relevant_space_size, relevant_viewport; + const int len = 100; + Eina_Size2D size_buffer[len]; + Efl_Gfx_Entity *obj_buffer[len]; if (!pd->size) return; if (pd->average_item_size <= 0) return; @@ -189,13 +187,13 @@ position_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd) { //it is important to first make the segment visible here, and then hide the rest //otherwise we get a state where item_container has 0 subchildren, which triggers a lot of focus logic. - vis_change_segment(pd, start_id, end_id, EINA_TRUE); - vis_change_segment(pd, pd->prev_run.start_id, pd->prev_run.end_id, EINA_FALSE); + vis_change_segment(&pd->object, start_id, end_id, EINA_TRUE); + vis_change_segment(&pd->object, pd->prev_run.start_id, pd->prev_run.end_id, EINA_FALSE); } else { - vis_change_segment(pd, pd->prev_run.start_id, start_id, (pd->prev_run.start_id > start_id)); - vis_change_segment(pd, pd->prev_run.end_id, end_id, (pd->prev_run.end_id < end_id)); + vis_change_segment(&pd->object, pd->prev_run.start_id, start_id, (pd->prev_run.start_id > start_id)); + vis_change_segment(&pd->object, pd->prev_run.end_id, end_id, (pd->prev_run.end_id < end_id)); } geom = pd->viewport; @@ -209,9 +207,20 @@ position_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd) { Eina_Size2D size; Efl_Gfx_Entity *ent = NULL; + int buffer_id = (i-start_id) % len; - EINA_SAFETY_ON_FALSE_RETURN(eina_accessor_data_get(pd->size_acc, i, (void**) &size)); - EINA_SAFETY_ON_FALSE_RETURN(eina_accessor_data_get(pd->content_acc, i, (void**) &ent)); + if (buffer_id == 0) + { + int res1, res2; + + res1 = _fill_buffer(&pd->object, i, len, obj_buffer); + res2 = _fill_buffer(&pd->min_size, i, len, size_buffer); + EINA_SAFETY_ON_FALSE_RETURN(res1 == res2); + EINA_SAFETY_ON_FALSE_RETURN(res2 > 0); + } + + size = size_buffer[buffer_id]; + ent = obj_buffer[buffer_id]; if (pd->dir == EFL_UI_LAYOUT_ORIENTATION_VERTICAL) geom.h = size.h; @@ -253,11 +262,15 @@ schedule_recalc_absolut_size(Eo *obj, Efl_Ui_Position_Manager_List_Data *pd) } EOLIAN static void -_efl_ui_position_manager_list_efl_ui_position_manager_entity_data_access_set(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd, Eina_Accessor *content_access, Eina_Accessor *size_access, int size) +_efl_ui_position_manager_list_efl_ui_position_manager_entity_data_access_set(Eo *obj, Efl_Ui_Position_Manager_List_Data *pd, void *obj_access_data, Efl_Ui_Position_Manager_Batch_Access_Entity obj_access, Eina_Free_Cb obj_access_free_cb, void *size_access_data, Efl_Ui_Position_Manager_Batch_Access_Size size_access, Eina_Free_Cb size_access_free_cb, int size) { cache_invalidate(obj, pd); - pd->content_acc = content_access; - pd->size_acc = size_access; + pd->object.data = obj_access_data; + pd->object.access = obj_access; + pd->object.free_cb = obj_access_free_cb; + pd->min_size.data = size_access_data; + pd->min_size.access = size_access; + pd->min_size.free_cb = size_access_free_cb; pd->size = size; } @@ -314,6 +327,7 @@ _efl_ui_position_manager_list_efl_ui_position_manager_entity_position_single_ite Eina_Size2D space_size; int relevant_space_size; Eina_Size2D size; + Eina_Size2D size_buffer[1]; if (!pd->size) return EINA_RECT(0,0,0,0); @@ -333,7 +347,9 @@ _efl_ui_position_manager_list_efl_ui_position_manager_entity_position_single_ite geom = pd->viewport; - eina_accessor_data_get(pd->size_acc, idx, (void**)&size); + EINA_SAFETY_ON_FALSE_RETURN_VAL(_fill_buffer(&pd->min_size, idx, 1, size_buffer) == 1, EINA_RECT_EMPTY()); + + size = size_buffer[0]; if (pd->dir == EFL_UI_LAYOUT_ORIENTATION_VERTICAL) { @@ -360,7 +376,7 @@ _efl_ui_position_manager_list_efl_ui_layout_orientable_orientation_set(Eo *obj E { pd->dir = dir; //in order to reset the state of the visible items, just hide everything and set the old segment accordingly - vis_change_segment(pd, pd->prev_run.start_id, pd->prev_run.end_id, EINA_FALSE); + vis_change_segment(&pd->object, pd->prev_run.start_id, pd->prev_run.end_id, EINA_FALSE); pd->prev_run.start_id = 0; pd->prev_run.end_id = 0; diff --git a/src/tests/elementary/efl_ui_test_position_manager_common.c b/src/tests/elementary/efl_ui_test_position_manager_common.c index 7cf39f92d8..ea89662837 100644 --- a/src/tests/elementary/efl_ui_test_position_manager_common.c +++ b/src/tests/elementary/efl_ui_test_position_manager_common.c @@ -12,8 +12,7 @@ static Eo* win; static Eina_Array *arr_obj; static Eina_Inarray *arr_size; -static Eina_Accessor inner_size_acc; -static Eina_Accessor *size_acc; + static void item_container_setup() { @@ -26,54 +25,44 @@ item_container_teardown() win = NULL; } -static Eina_Bool -_get_at(Eina_Accessor *it EINA_UNUSED, unsigned int idx, void **data) +static int +_size_accessor_get_at(void *data EINA_UNUSED, int start_id, Eina_Rw_Slice memory) { - Eina_Size2D *result_ptr = (void*)data; - Eina_Size2D *inner_result; + int i; - if (!eina_accessor_data_get(size_acc, idx, (void*)&inner_result)) - return EINA_FALSE; - *result_ptr = *inner_result; - return EINA_TRUE; + for (i = start_id; i < (int)(MIN(start_id + memory.len, eina_inarray_count(arr_size))); ++i) + { + Eina_Size2D *size = eina_inarray_nth(arr_size, i); + + ((Eina_Size2D*)memory.mem)[i - start_id] = *size; + } + return i - start_id; } -static void -_free_cb(Eina_Accessor *it EINA_UNUSED) +static int +_obj_accessor_get_at(void *data EINA_UNUSED, int start_id, Eina_Rw_Slice memory) { - eina_accessor_free(size_acc); + int i; + + for (i = start_id; i < (int)(MIN(start_id + memory.len, eina_array_count(arr_obj))); ++i) + { + Efl_Gfx_Entity *geom = eina_array_data_get(arr_obj, i); + + ((Efl_Gfx_Entity**)memory.mem)[i - start_id] = geom; + } + + return i - start_id; } - -static Eina_Bool -_lock_cb(Eina_Accessor *it EINA_UNUSED) -{ - return eina_accessor_lock(size_acc); -} - -static Eina_Accessor* -_clone_cb(Eina_Accessor *it EINA_UNUSED) -{ - return eina_accessor_clone(size_acc); -} - - static void _initial_setup(void) { arr_obj = eina_array_new(10); arr_size = eina_inarray_new(sizeof(Eina_Size2D), 10); - size_acc = eina_inarray_accessor_new(arr_size); - - inner_size_acc.version = EINA_ACCESSOR_VERSION; - EINA_MAGIC_SET(&inner_size_acc, EINA_MAGIC_ACCESSOR); - inner_size_acc.get_at = _get_at; - inner_size_acc.free = _free_cb; - inner_size_acc.lock = _lock_cb; - inner_size_acc.clone = _clone_cb; efl_ui_position_manager_entity_data_access_set(position_manager, - eina_array_accessor_new(arr_obj), - &inner_size_acc, 0); + NULL, _obj_accessor_get_at, NULL, + NULL, _size_accessor_get_at, NULL, + 0); } static int