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 <cedric.bail@free.fr>
Differential Revision: https://phab.enlightenment.org/D9445
This commit is contained in:
Marcel Hollerbach 2019-07-30 11:13:46 +02:00 committed by Cedric BAIL
parent 69975fc72d
commit d98d434e56
6 changed files with 230 additions and 145 deletions

View File

@ -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);
}

View File

@ -0,0 +1,48 @@
#ifndef EFL_UI_POSITION_MANAGER_COMMON_H
#define EFL_UI_POSITION_MANAGER_COMMON_H 1
#include <Eina.h>
#include <Efl_Ui.h>
#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

View File

@ -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<Efl.Gfx.Entity>; [[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<Efl.Gfx.Entity>; [[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<Efl.Gfx.Entity>; [[The accessor for canvas obejcts, even if the id is valid, the returned object may be NULL]]
size_access : accessor<Eina.Size2D>; [[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 {

View File

@ -6,13 +6,14 @@
#include <Elementary.h>
#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);

View File

@ -7,13 +7,14 @@
#include <Elementary.h>
#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;

View File

@ -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