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:
parent
69975fc72d
commit
d98d434e56
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue