efl_ui_position_manager: refactor data access

before data access has been a property on
Efl.Ui.Position_Manager.Entity. However, we are not sure how stable all
this will be, and maybe we have the demand to change that in future, in
order to allow more high-performance item passing here.

Additionally, this patch addresses a few lectures learned from the past,
that includes:
- direct group header filling.
- direct group sizing
- difference between size for caching, and size for displaying
- Have a end_id which is the maximum of id that is filled.

ref T8179

Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Differential Revision: https://phab.enlightenment.org/D9754
This commit is contained in:
Marcel Hollerbach 2019-08-27 13:35:33 +02:00
parent 47547ff088
commit 53739890ce
12 changed files with 362 additions and 239 deletions

View File

@ -257,6 +257,7 @@ typedef Eo Efl_Ui_Spotlight_Indicator;
# include <efl_ui_slider.eo.h>
# include <efl_ui_item.eo.h>
# include <efl_ui_position_manager_entity.eo.h>
# include <efl_ui_position_manager_data_access_v1.eo.h>
# include <efl_ui_collection.eo.h>
# include <efl_ui_position_manager_list.eo.h>
# include <efl_ui_position_manager_grid.eo.h>

View File

@ -266,38 +266,47 @@ _efl_ui_collection_efl_ui_multi_selectable_selected_items_get(Eo *obj EINA_UNUSE
}
static inline void
_fill_group_flag(Eo *item, Efl_Ui_Position_Manager_Batch_Group_State *flag)
_fill_depth(Eo *item, unsigned char *depth, Eina_Bool *leader)
{
if (efl_isa(item, EFL_UI_GROUP_ITEM_CLASS))
*flag = EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_GROUP;
{
*depth = 1;
*leader = EINA_TRUE;
}
else if (efl_ui_item_parent_get(item))
*flag = EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_PART_OF_GROUP;
{
*depth = 1;
*leader = EINA_FALSE;
}
else
*flag = EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_NO_GROUP;
{
*leader = EINA_FALSE;
*depth = 0;
}
}
static Efl_Ui_Position_Manager_Batch_Result
_size_accessor_get_at(void *data, int start_id, Eina_Rw_Slice memory)
static Efl_Ui_Position_Manager_Size_Batch_Result
_size_accessor_get_at(void *data, Efl_Ui_Position_Manager_Size_Call_Config conf, Eina_Rw_Slice memory)
{
Fast_Accessor *accessor = data;
size_t i;
const Eina_List *lst = _fast_accessor_get_at(accessor, start_id);
Efl_Ui_Position_Manager_Batch_Size_Access *sizes = memory.mem;
Efl_Ui_Position_Manager_Batch_Result result = {-1, 0};
const Eina_List *lst = _fast_accessor_get_at(accessor, conf.range.start_id);
Efl_Ui_Position_Manager_Size_Batch_Entity *sizes = memory.mem;
Efl_Ui_Position_Manager_Size_Batch_Result result = {0};
EINA_SAFETY_ON_NULL_RETURN_VAL(lst, result);
for (i = 0; i < memory.len; ++i)
for (i = 0; i < (conf.range.end_id - conf.range.start_id); ++i)
{
Efl_Gfx_Entity *geom = eina_list_data_get(lst), *parent;
Eina_Size2D size = efl_gfx_hint_size_min_get(geom);
parent = efl_ui_item_parent_get(geom);
sizes[i].size = size;
_fill_group_flag(geom, &sizes[i].group);
if (i == 0 && sizes[0].group != EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_GROUP && parent)
_fill_depth(geom, &sizes[i].element_depth, &sizes[i].depth_leader);
if (i == 0 && !sizes[0].depth_leader && parent)
{
result.group_id = efl_pack_index_get(efl_ui_item_container_get(parent), parent);
result.parent_size = efl_gfx_hint_size_min_get(parent);
}
lst = eina_list_next(lst);
if (!lst)
@ -311,25 +320,25 @@ _size_accessor_get_at(void *data, int start_id, Eina_Rw_Slice memory)
return result;
}
static Efl_Ui_Position_Manager_Batch_Result
_obj_accessor_get_at(void *data, int start_id, Eina_Rw_Slice memory)
static Efl_Ui_Position_Manager_Object_Batch_Result
_obj_accessor_get_at(void *data, Efl_Ui_Position_Manager_Request_Range range, Eina_Rw_Slice memory)
{
Fast_Accessor *accessor = data;
size_t i;
const Eina_List *lst = _fast_accessor_get_at(accessor, start_id);
Efl_Ui_Position_Manager_Batch_Entity_Access *objs = memory.mem;
Efl_Ui_Position_Manager_Batch_Result result = {-1, 0};
const Eina_List *lst = _fast_accessor_get_at(accessor, range.start_id);
Efl_Ui_Position_Manager_Object_Batch_Entity *objs = memory.mem;
Efl_Ui_Position_Manager_Object_Batch_Result result = {0};
for (i = 0; i < memory.len; ++i)
for (i = 0; i < range.end_id - range.start_id; ++i)
{
Efl_Gfx_Entity *geom = eina_list_data_get(lst), *parent;
parent = efl_ui_item_parent_get(geom);
objs[i].entity = geom;
_fill_group_flag(geom, &objs[i].group);
if (i == 0 && objs[0].group != EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_GROUP && parent)
_fill_depth(geom, &objs[i].element_depth, &objs[i].depth_leader);
if (i == 0 && !objs[0].depth_leader && parent)
{
result.group_id = efl_pack_index_get(efl_ui_item_container_get(parent), parent);
result.group = parent;
}
lst = eina_list_next(lst);
@ -344,6 +353,7 @@ _obj_accessor_get_at(void *data, int start_id, Eina_Rw_Slice memory)
return result;
}
EOLIAN static Efl_Object*
_efl_ui_collection_efl_object_constructor(Eo *obj, Efl_Ui_Collection_Data *pd EINA_UNUSED)
{
@ -864,7 +874,6 @@ _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, NULL, NULL, NULL, NULL, 0);
efl_del(pd->pos_man);
}
pd->pos_man = layouter;
@ -872,11 +881,16 @@ _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, _obj_accessor_get_at, NULL,
&pd->size_accessor, _size_accessor_get_at, NULL,
eina_list_count(pd->items));
switch(efl_ui_position_manager_entity_version(pd->pos_man, 1))
{
case 1:
efl_ui_position_manager_data_access_v1_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));
break;
}
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

@ -6,36 +6,90 @@
#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;
struct {
void *data;
Efl_Ui_Position_Manager_Size_Batch_Callback access; //this can also be the size accessor, but that does not matter here
Eina_Free_Cb free_cb;
} size;
struct {
void *data;
Efl_Ui_Position_Manager_Object_Batch_Callback access; //this can also be the size accessor, but that does not matter here
Eina_Free_Cb free_cb;
} object;
} Api_Callbacks;
typedef struct {
unsigned int start_id, end_id;
} Vis_Segment;
static inline int
_fill_buffer(Api_Callback *cb , int start_id, int len, int *group_id, void *data)
static Efl_Ui_Position_Manager_Size_Batch_Result
_batch_request_size(Api_Callbacks cb , int start_id, int len, Eina_Bool cache, void *data)
{
Efl_Ui_Position_Manager_Batch_Result res;
Efl_Ui_Position_Manager_Size_Batch_Result res;
Eina_Rw_Slice slice;
slice.mem = data;
slice.len = len;
res = cb->access(cb->data, start_id, slice);
Efl_Ui_Position_Manager_Size_Call_Config conf;
conf.cache_request = cache;
conf.range.start_id = start_id;
conf.range.end_id = start_id + len;
if (group_id)
*group_id = res.group_id;
res = cb.size.access(cb.size.data, conf, slice);
return res.filled_items;
return res;
}
#define BATCH_ACCESS_SIZE(cb, start_id, len, cache, data) \
do { \
size_result = _batch_request_size((cb), (start_id), (len), (cache), (data)); \
EINA_SAFETY_ON_FALSE_RETURN(size_result.filled_items > 0); \
} while(0);
#define BATCH_ACCESS_SIZE_VAL(cb, start_id, len, cache, data, V) \
do { \
size_result = _batch_request_size((cb), (start_id), (len), (cache), (data)); \
EINA_SAFETY_ON_FALSE_RETURN_VAL(size_result.filled_items > 0, V); \
} while(0);
static Efl_Ui_Position_Manager_Object_Batch_Result
_batch_request_objects(Api_Callbacks cb , int start_id, int len, void *data)
{
Efl_Ui_Position_Manager_Object_Batch_Result res;
Eina_Rw_Slice slice;
slice.mem = data;
slice.len = len;
Efl_Ui_Position_Manager_Request_Range range;
range.start_id = start_id;
range.end_id = start_id + len;
res = cb.object.access(cb.object.data, range, slice);
return res;
}
#define BATCH_ACCESS_OBJECT(cb, start_id, len, data) \
do { \
object_result = _batch_request_objects((cb), (start_id), (len), (data)); \
EINA_SAFETY_ON_FALSE_RETURN(object_result.filled_items > 0); \
} while(0);
#define BATCH_ACCESS_OBJECT_VAL(cb, start_id, len, data, v) \
do { \
object_result = _batch_request_objects((cb), (start_id), (len), (data)); \
EINA_SAFETY_ON_FALSE_RETURN_VAL(object_result.filled_items > 0, v); \
} while(0);
static inline void
vis_change_segment(Api_Callback *cb, int a, int b, Eina_Bool flag)
vis_change_segment(Api_Callbacks cb, int a, int b, Eina_Bool flag)
{
const int len = 50;
Efl_Ui_Position_Manager_Batch_Entity_Access data[len];
Efl_Ui_Position_Manager_Object_Batch_Entity data[len];
Efl_Ui_Position_Manager_Object_Batch_Result object_result;
if (a == b) return;
@ -46,7 +100,7 @@ vis_change_segment(Api_Callback *cb, int a, int b, Eina_Bool flag)
if (buffer_id == 0)
{
EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(cb, MIN(a,b), len, NULL, data) >= 0);
BATCH_ACCESS_OBJECT(cb, i, len, data);
}
ent = data[buffer_id].entity;
if (ent && !flag && (efl_ui_focus_object_focus_get(ent) || efl_ui_focus_object_child_focus_get(ent)))
@ -60,10 +114,9 @@ vis_change_segment(Api_Callback *cb, int a, int b, Eina_Bool flag)
}
}
}
#endif
static inline void
vis_segment_swap(Api_Callback *cb, Vis_Segment new, Vis_Segment old)
vis_segment_swap(Api_Callbacks cb, Vis_Segment new, Vis_Segment old)
{
if (new.end_id <= old.start_id || new.start_id >= old.end_id)
{
@ -78,3 +131,5 @@ vis_segment_swap(Api_Callback *cb, Vis_Segment new, Vis_Segment old)
vis_change_segment(cb, old.end_id, new.end_id, (old.end_id < new.end_id));
}
}
#endif

View File

@ -0,0 +1,101 @@
struct @beta Efl.Ui.Position_Manager.Request_Range {
[[Representing the range of a request.]]
start_id : uint; [[The first item that must be filled into the passed slice.]]
end_id : uint; [[The last item that must be filled into the passed slice.]]
}
struct @beta Efl.Ui.Position_Manager.Object_Batch_Entity{
[[Struct that is getting filled by the object function callback.]]
entity : Efl.Gfx.Entity; [[The canvas object.]]
element_depth : ubyte; [[The depth change in this returned entity.
Every Element has a depth, if the parent is $null the depth is 0.
Every step deeper into the hirachy is exactly one depth deeper.
If this depth has been different to the previous item, then this element can be seen as the group leader. The following elements with the same depth are in the same group.]]
depth_leader : bool; [[$true if this is the leader of a group]]
}
struct @beta Efl.Ui.Position_Manager.Size_Batch_Entity{
[[Struct that is getting filled by the size function callback.]]
size : Eina.Size2D; [[The size of the element.]]
element_depth : ubyte; [[The depth change in this returned entity.
Every Element has a depth, if the parent is $null the depth is 0.
Every step deeper into the hirachy is exactly one depth deeper.
If this depth has been different to the previous item, then this element can be seen as the group leader. The following elements with the same depth are in the same group.]]
depth_leader : bool; [[$true if this is the leader of a group]]
}
struct @beta Efl.Ui.Position_Manager.Size_Batch_Result {
[[Struct returned by the size access callback.]]
parent_size : Eina.Size2D; [[The group size of the group where the first item is part of.]]
parent_depth : ubyte; [[The depth of the parent]]
filled_items : uint; [[The number of items that are filled into the slice.]]
}
struct @beta Efl.Ui.Position_Manager.Size_Call_Config {
[[Struct that is returned by the function callbacks.]]
range : Efl.Ui.Position_Manager.Request_Range; [[The range of items to fill into @.memory. The length of memory must be bigger or equal to the requested items]] // This struct does not contain a @.memory field.
cache_request : bool; [[Indicate if this request is made for caching or displaying. If its for caching, the data-provider will fill in approximations, instead of doing heavy lifting from some backend. If this is not a caching call, the exact size should be requested and delivered at some later point.]]
}
struct @beta Efl.Ui.Position_Manager.Object_Batch_Result {
[[Struct returned by the object access callback]]
group : Efl.Ui.Item; [[The group where the first item is part of]]
parent_depth : ubyte; [[The depth of the parent]]
filled_items : uint; [[The number of items that are filled into the slice]]
}
function @beta Efl.Ui.Position_Manager.Object_Batch_Callback {
[[ Function callback for getting a batch of items.]]
params {
range : Efl.Ui.Position_Manager.Request_Range; [[The range of items to fill into @.memory. The length of memory must be bigger or equal to the requested items]]
memory : rw_slice<Efl.Ui.Position_Manager.Object_Batch_Entity>; [[The slice to fill the information in, the full slice will be filled if there are enough items]]
}
return: Efl.Ui.Position_Manager.Object_Batch_Result; [[The returned stats of this function call.]]
};
function @beta Efl.Ui.Position_Manager.Size_Batch_Callback {
[[ Function callback for getting sizes of a batch of items.]]
params {
conf : Efl.Ui.Position_Manager.Size_Call_Config; [[The configution for this call]]
memory : rw_slice<Efl.Ui.Position_Manager.Size_Batch_Entity>; [[The slice to fill the information in, the full slice will be filled if there are enough items]]
}
return: Efl.Ui.Position_Manager.Size_Batch_Result; [[The returned stats of this function call]]
};
interface @beta Efl.Ui.Position_Manager.Data_Access_V1 {
[[Interface for abstracting the data access of the position managers.
The idea here is that a data-provider, calls @.data_access on the positon manager object and passes the functions that are defined here. At any pointer later in time, the position manager can call these function callbacks to get sizes or objects.
A data-provider should always fill all requested items. If a item is not available $null is inserted. If a size is not available, a as-close-as-possible approximation should be inserted.
The Size callback is equipped with a parameter for if this is a caching request or not. This flag can be used to differentiate between two usecases. The size can be requested for building up a cache over all items. The size can also be requested for applying it to the object. The data-provider might needs to do heavy loading for getting the right size available, in case of a cache build up the as-close-as-possible aproximation is enough there. If it is real placement, the size should be correct.
If a size changes after it was returned due to batching, this change still should be annonced with the @Efl.Ui.Position_Manager.Entity.item_size_changed function.
The depth of the items is used to express a hierachical structure on the items themselves.
Any given depth might or might not have a $depth_leader.
A group is ended when there is either a lower depth, or another depth_leader.
]]
methods {
@property data_access {
[[This gives access to items to be managed. The manager reads this information and modifies the retrieved items' positions and sizes.
$obj_access gives access to the graphical entitites to manage. Some of them might be NULL, meaning they are not yet ready to be displayed. Their size in the $size_access array will be correct, though, so other entities can still be positioned correctly.
Typically, only entities inside the viewport will be retrieved.
$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 @Efl.Ui.Position_Manager.Entity.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 : Efl.Ui.Position_Manager.Object_Batch_Callback; [[Function callback for canvas objects, even if the start_id is valid, the returned objects may be NULL.]]
size_access : Efl.Ui.Position_Manager.Size_Batch_Callback; [[Function callback for the size, returned values are always valid, but might be changed later on.]]
size : int; [[valid size for start_id, 0 <= i < size]]
}
}
}
}

View File

@ -12,3 +12,4 @@
#define MY_CLASS EFL_UI_POSITION_MANAGER_ENTITY_CLASS
#include "efl_ui_position_manager_entity.eo.c"
#include "efl_ui_position_manager_data_access_v1.eo.c"

View File

@ -1,49 +1,5 @@
import efl_ui;
enum Efl.Ui.Position_Manager.Batch_Group_State{
[[Enum expressing the group related state of a item.]]
no_group = 0, [[This item is not a group item and is not part of any group.]]
group = 1, [[This item is a group item.]]
part_of_group = 2 [[This item is part of a group.]]
}
struct Efl.Ui.Position_Manager.Batch_Entity_Access{
[[Struct that is getting filled by the object function callback.]]
entity : Efl.Gfx.Entity; [[The canvas object.]]
group : Efl.Ui.Position_Manager.Batch_Group_State; [[If this is a group item.]]
}
struct Efl.Ui.Position_Manager.Batch_Size_Access{
[[Struct that is getting filled by the size function callback.]]
size : Eina.Size2D; [[The size of the element.]]
group : Efl.Ui.Position_Manager.Batch_Group_State; [[If this is a group item.]]
}
struct Efl.Ui.Position_Manager.Batch_Result {
[[Struct that is returned by the function callbacks.]]
group_id : int; [[The group of the first item. If the first item is a group, or the first item does not have a group, -1 will be the id]]
filled_items : int; [[The number of items that are filled into the slice]]
}
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.Ui.Position_Manager.Batch_Entity_Access>; [[The slice to fill the information in, the full slice will be filled if there are enough items]]
}
return: Efl.Ui.Position_Manager.Batch_Result; [[The returned stats of this function call.]]
};
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.Ui.Position_Manager.Batch_Size_Access>; [[The slice to fill the information in, the full slice will be filled if there are enough items]]
}
return: Efl.Ui.Position_Manager.Batch_Result; [[The returned stats of this function call]]
};
struct Efl.Ui.Position_Manager.Range_Update {
[[A struct containing the the updated range of visible items in this position manger.]]
start_id : uint; [[The first item that is visible]]
@ -58,25 +14,14 @@ interface @beta Efl.Ui.Position_Manager.Entity extends Efl.Ui.Layout_Orientable
The interface gets a defined set of elements that is meant to be displayed. The implementation provides a way to calculate the size that is required to display all items. Every time this absolut size of items is changed, content_size,changed is called.
]]
methods {
@property data_access {
[[This gives access to items to be managed. The manager reads this information and modifies the retrieved items' positions and sizes.
$obj_access gives access to the graphical entitites to manage. Some of them might be NULL, meaning they are not yet ready to be displayed. Their size in the $size_access array will be correct, though, so other entities can still be positioned correctly.
Typically, only entities inside the viewport will be retrieved.
$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 : 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]]
}
version {
[[ Return the version of Data_Access that is used.
This object needs to implement the interface Efl.Ui.Position_Manager.Data_Access_V1 if 1 is returned. 2 if V2 (not available yet) is implemented.
]]
params {
max : int; [[The maximum version that is available from the data-provider.]]
}
return : int; [[The version that should be used here. 0 is an error.]]
}
@property viewport {
[[This is the position and size of the viewport, where elements are displayed in.
@ -118,7 +63,7 @@ interface @beta Efl.Ui.Position_Manager.Entity extends Efl.Ui.Layout_Orientable
item_added {
[[The new item $subobj has been added at the $added_index field.
The accessor provided through @.data_access will contain updated Entities.]]
The accessor provided through @Efl.Ui.Position_Manager.Data_Access_V1.data_access will contain updated Entities.]]
params {
added_index : int;
subobj : Efl.Gfx.Entity;
@ -126,7 +71,7 @@ interface @beta Efl.Ui.Position_Manager.Entity extends Efl.Ui.Layout_Orientable
}
item_removed {
[[The item $subobj previously at position $removed_index has been removed.
The accessor provided through @.data_access will contain updated Entities.
The accessor provided through @Efl.Ui.Position_Manager.Data_Access_V1.data_access will contain updated Entities.
]]
params {
removed_index : int;

View File

@ -13,7 +13,6 @@
Efl_Ui_Position_Manager_Grid_Data *pd = efl_data_scope_get(obj, MY_CLASS);
typedef struct {
Api_Callback min_size, object;
unsigned int size;
unsigned int groups;
Eina_Rect viewport;
@ -30,6 +29,7 @@ typedef struct {
Eina_Bool size_cache_dirty;
Eo *last_group;
Eina_Future *rebuild_absolut_size;
Api_Callbacks callbacks;
} Efl_Ui_Position_Manager_Grid_Data;
typedef struct {
@ -43,7 +43,8 @@ _group_cache_require(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd)
{
unsigned int i;
const int len = 100;
Efl_Ui_Position_Manager_Batch_Size_Access size_buffer[len];
Efl_Ui_Position_Manager_Size_Batch_Entity size_buffer[len];
Efl_Ui_Position_Manager_Size_Batch_Result size_result;
Group_Cache_Line line = { 0 };
if (!pd->group_cache_dirty)
@ -60,22 +61,22 @@ _group_cache_require(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd)
if (buffer_id == 0)
{
EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->min_size, i, len, NULL, size_buffer) > 0);
BATCH_ACCESS_SIZE(pd->callbacks, i, MIN(len, pd->size - i), EINA_TRUE, size_buffer);
}
if (size_buffer[buffer_id].group == EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_GROUP)
if (size_buffer[buffer_id].depth_leader)
{
eina_inarray_push(pd->group_cache, &line);
line.real_group = EINA_TRUE;
line.group_header_size = size_buffer[buffer_id].size;
line.items = 1;
}
else if (size_buffer[buffer_id].group == EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_PART_OF_GROUP ||
(!line.real_group && size_buffer[buffer_id].group == EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_NO_GROUP))
else if (size_buffer[buffer_id].element_depth > 0 ||
(!line.real_group && size_buffer[buffer_id].element_depth == 0))
{
line.items ++;
}
else if (size_buffer[buffer_id].group == EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_NO_GROUP && line.real_group)
else if (size_buffer[buffer_id].element_depth == 0 && line.real_group)
{
eina_inarray_push(pd->group_cache, &line);
line.real_group = EINA_FALSE;
@ -240,7 +241,10 @@ _position_items_vertical(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data
unsigned int i;
const int len = 100;
int columns, last_block_start = ctx->new.start_id;
Efl_Ui_Position_Manager_Batch_Entity_Access obj_buffer[len];
Efl_Ui_Position_Manager_Size_Batch_Entity size_buffer[len];
Efl_Ui_Position_Manager_Size_Batch_Result size_result;
Efl_Ui_Position_Manager_Object_Batch_Entity obj_buffer[len];
Efl_Ui_Position_Manager_Object_Batch_Result object_result;
if (!pd->viewport.w || !pd->viewport.h) return;
@ -252,17 +256,13 @@ _position_items_vertical(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data
int buffer_id = (i-ctx->new.start_id) % len;
if (buffer_id == 0)
{
int tmp_group;
BATCH_ACCESS_SIZE(pd->callbacks, i, len, EINA_FALSE, size_buffer);
BATCH_ACCESS_OBJECT(pd->callbacks, i, len, obj_buffer);
EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->object, i, len, &tmp_group, obj_buffer) > 0);
if (tmp_group != -1 && i == ctx->new.start_id)
if (i == ctx->new.start_id)
{
Efl_Ui_Position_Manager_Batch_Size_Access size_buffer[1];
Efl_Ui_Position_Manager_Batch_Entity_Access obj_buffer[1];
EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->min_size, tmp_group, 1, NULL, size_buffer) != 0);
EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->object, tmp_group, 1, NULL, obj_buffer) != 0);
ctx->floating_group = obj_buffer[0].entity;
ctx->floating_size.h = size_buffer[0].size.h;
ctx->floating_group = object_result.group;
ctx->floating_size = size_result.parent_size;
ctx->floating_size.w = pd->viewport.w;
}
}
@ -274,19 +274,16 @@ _position_items_vertical(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data
if (obj_buffer[buffer_id].entity == pd->last_group)
pd->last_group = NULL;
if (obj_buffer[buffer_id].group == EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_GROUP)
if (obj_buffer[buffer_id].depth_leader)
{
Efl_Ui_Position_Manager_Batch_Size_Access size_buffer[1];
EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->min_size, i, 1, NULL, size_buffer) == 1);
if (x != 0)
y += 1;
last_block_start = i + 1;
start.y += size_buffer[0].size.h + y*pd->max_min_size.h;
start.y += size_buffer[buffer_id].size.h + y*pd->max_min_size.h;
geom.size = pd->viewport.size;
geom.h = size_buffer[0].size.h;
geom.h = size_buffer[buffer_id].size.h;
geom.y += y*pd->max_min_size.h;
if (!ctx->placed_item)
ctx->placed_item = obj_buffer[buffer_id].entity;
@ -307,7 +304,10 @@ _position_items_horizontal(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Dat
unsigned int i;
const int len = 100;
int columns, last_block_start = ctx->new.start_id;
Efl_Ui_Position_Manager_Batch_Entity_Access obj_buffer[len];
Efl_Ui_Position_Manager_Size_Batch_Entity size_buffer[len];
Efl_Ui_Position_Manager_Size_Batch_Result size_result;
Efl_Ui_Position_Manager_Object_Batch_Entity obj_buffer[len];
Efl_Ui_Position_Manager_Object_Batch_Result object_result;
if (!pd->viewport.w || !pd->viewport.h) return;
@ -319,20 +319,16 @@ _position_items_horizontal(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Dat
int buffer_id = (i-ctx->new.start_id) % len;
if (buffer_id == 0)
{
int tmp_group;
BATCH_ACCESS_SIZE(pd->callbacks, i, len, EINA_FALSE, size_buffer);
BATCH_ACCESS_OBJECT(pd->callbacks, i, len, obj_buffer);
EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->object, i, len, &tmp_group, obj_buffer) > 0);
if (tmp_group != -1 && i == ctx->new.start_id && pd->dir != EFL_UI_LAYOUT_ORIENTATION_VERTICAL)
if (i == ctx->new.start_id)
{
Efl_Ui_Position_Manager_Batch_Size_Access size_buffer[1];
Efl_Ui_Position_Manager_Batch_Entity_Access obj_buffer[1];
EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->min_size, tmp_group, 1, NULL, size_buffer) != 0);
EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->object, tmp_group, 1, NULL, obj_buffer) != 0);
start.y += size_buffer[0].size.h;
columns = (pd->viewport.h - size_buffer[0].size.h)/pd->max_min_size.h;
ctx->floating_group = obj_buffer[0].entity;
ctx->floating_size.h = size_buffer[0].size.h;
ctx->floating_group = object_result.group;
ctx->floating_size = size_result.parent_size;
ctx->floating_size.w = pd->viewport.w;
start.y += size_result.parent_size.h;
columns = (pd->viewport.h - size_result.parent_size.h)/pd->max_min_size.h;
}
}
Eina_Rect geom;
@ -344,21 +340,18 @@ _position_items_horizontal(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Dat
if (obj_buffer[buffer_id].entity == pd->last_group)
pd->last_group = NULL;
if (obj_buffer[buffer_id].group == EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_GROUP)
if (obj_buffer[buffer_id].depth_leader)
{
Efl_Ui_Position_Manager_Batch_Size_Access size_buffer[1];
EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->min_size, i, 1, NULL, size_buffer) == 1);
last_block_start = i + 1;
start.y = pd->viewport.y + size_buffer[0].size.h;
start.y = pd->viewport.y + size_buffer[buffer_id].size.h;
start.x += x*pd->max_min_size.w;
geom.size.h = size_buffer[0].size.h;
geom.size.h = size_buffer[buffer_id].size.h;
geom.size.w = pd->viewport.w;
geom.x += x*pd->max_min_size.w;
geom.y = pd->viewport.y;
columns = (pd->viewport.h - size_buffer[0].size.h)/pd->max_min_size.h;
columns = (pd->viewport.h - size_buffer[buffer_id].size.h)/pd->max_min_size.h;
if (!ctx->placed_item)
ctx->placed_item = obj_buffer[buffer_id].entity;
}
@ -456,7 +449,7 @@ _reposition_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd)
//to performance optimize the whole widget, we are setting the objects that are outside the viewport to visibility false
//The code below ensures that things outside the viewport are always hidden, and things inside the viewport are visible
vis_segment_swap(&pd->object, cur, pd->prev_run);
vis_segment_swap(pd->callbacks, cur, pd->prev_run);
ctx.new = cur;
ctx.consumed_space = consumed_space;
@ -539,18 +532,6 @@ _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, 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->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;
}
EOLIAN static void
_efl_ui_position_manager_grid_efl_ui_position_manager_entity_viewport_set(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd, Eina_Rect viewport)
{
@ -594,13 +575,14 @@ _schedule_recalc_abs_size(Eo *obj, Efl_Ui_Position_Manager_Grid_Data *pd)
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)
{
Efl_Ui_Position_Manager_Batch_Size_Access size[1];
Efl_Ui_Position_Manager_Size_Batch_Entity size_buffer[1];
Efl_Ui_Position_Manager_Size_Batch_Result size_result;
pd->size ++;
efl_gfx_entity_visible_set(subobj, EINA_FALSE);
_group_cache_invalidate(obj, pd);
EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->min_size, added_index, 1, NULL, &size) == 1);
_update_min_size(obj, pd, added_index, size[0].size);
BATCH_ACCESS_SIZE(pd->callbacks, added_index, 1, EINA_TRUE, size_buffer);
_update_min_size(obj, pd, added_index, size_buffer[0].size);
_flush_min_size(obj, pd);
_schedule_recalc_abs_size(obj, pd);
}
@ -622,16 +604,17 @@ 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;
Efl_Ui_Position_Manager_Batch_Size_Access data[len];
Efl_Ui_Position_Manager_Size_Batch_Entity size_buffer[len];
Efl_Ui_Position_Manager_Size_Batch_Result size_result;
for (int i = start_id; i <= end_id; ++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, NULL, data) >= 0);
BATCH_ACCESS_SIZE(pd->callbacks, i, len, EINA_TRUE, size_buffer);
}
_update_min_size(obj, pd, i, data[i-start_id].size);
_update_min_size(obj, pd, i, size_buffer[buffer_id].size);
}
_size_cache_invalidate(obj, pd);
_flush_min_size(obj, pd);
@ -662,11 +645,12 @@ _efl_ui_position_manager_grid_efl_ui_position_manager_entity_position_single_ite
unsigned int relevant_space_size;
unsigned int group_consumed_size = 0;
unsigned int group_consumed_ids = 0;
Efl_Ui_Position_Manager_Batch_Size_Access size_buffer[1];
Efl_Ui_Position_Manager_Size_Batch_Entity size_buffer[1];
Efl_Ui_Position_Manager_Size_Batch_Result size_result;
if (!pd->size) return EINA_RECT(0, 0, 0, 0);
if (pd->max_min_size.w <= 0 || pd->max_min_size.h <= 0) return EINA_RECT(0, 0, 0, 0);
EINA_SAFETY_ON_FALSE_RETURN_VAL(_fill_buffer(&pd->min_size, idx, 1, NULL, size_buffer) == 1, EINA_RECT_EMPTY());
BATCH_ACCESS_SIZE_VAL(pd->callbacks, idx, 1, EINA_TRUE, size_buffer, EINA_RECT_EMPTY());
_size_cache_require(obj, pd);
_flush_abs_size(obj, pd);
@ -761,4 +745,23 @@ _efl_ui_position_manager_grid_efl_ui_position_manager_entity_relative_item(Eo *o
return new_id;
}
EOLIAN static int
_efl_ui_position_manager_grid_efl_ui_position_manager_entity_version(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd EINA_UNUSED, int max EINA_UNUSED)
{
return 1;
}
EOLIAN static void
_efl_ui_position_manager_grid_efl_ui_position_manager_data_access_v1_data_access_set(Eo *obj, Efl_Ui_Position_Manager_Grid_Data *pd, void *obj_access_data, Efl_Ui_Position_Manager_Object_Batch_Callback obj_access, Eina_Free_Cb obj_access_free_cb, void *size_access_data, Efl_Ui_Position_Manager_Size_Batch_Callback size_access, Eina_Free_Cb size_access_free_cb, int size)
{
_group_cache_invalidate(obj, pd);
pd->callbacks.object.data = obj_access_data;
pd->callbacks.object.access = obj_access;
pd->callbacks.object.free_cb = obj_access_free_cb;
pd->callbacks.size.data = size_access_data;
pd->callbacks.size.access = size_access;
pd->callbacks.size.free_cb = size_access_free_cb;
pd->size = size;
}
#include "efl_ui_position_manager_grid.eo.c"

View File

@ -1,11 +1,11 @@
class @beta Efl.Ui.Position_Manager.Grid extends Efl.Object implements Efl.Ui.Position_Manager.Entity
class @beta Efl.Ui.Position_Manager.Grid extends Efl.Object implements Efl.Ui.Position_Manager.Entity, Efl.Ui.Position_Manager.Data_Access_V1
{
[[Implementation of @Efl.Ui.Position_Manager.Entity for two-dimensional grids.
Every item in the grid has the same size, which is the biggest minimum size of all items.
]]
implements {
Efl.Ui.Position_Manager.Entity.data_access {set;}
Efl.Ui.Position_Manager.Entity.version;
Efl.Ui.Position_Manager.Entity.viewport {set;}
Efl.Ui.Position_Manager.Entity.scroll_position {set;}
Efl.Ui.Position_Manager.Entity.item_added;
@ -14,5 +14,6 @@ class @beta Efl.Ui.Position_Manager.Grid extends Efl.Object implements Efl.Ui.Po
Efl.Ui.Position_Manager.Entity.item_size_changed;
Efl.Ui.Position_Manager.Entity.relative_item;
Efl.Ui.Layout_Orientable.orientation {set; get;}
Efl.Ui.Position_Manager.Data_Access_V1.data_access {set;}
}
}

View File

@ -14,7 +14,6 @@
Efl_Ui_Position_Manager_List_Data *pd = efl_data_scope_get(obj, MY_CLASS);
typedef struct {
Api_Callback min_size, object;
unsigned int size;
Eina_Future *rebuild_absolut_size;
Eina_Rect viewport;
@ -26,6 +25,7 @@ typedef struct {
int maximum_min_size;
Vis_Segment prev_run;
Efl_Gfx_Entity *last_group;
Api_Callbacks callbacks;
} Efl_Ui_Position_Manager_List_Data;
/*
@ -41,8 +41,8 @@ cache_require(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd)
{
unsigned int i;
const int len = 100;
Efl_Ui_Position_Manager_Batch_Size_Access size_buffer[100];
Efl_Ui_Position_Manager_Size_Batch_Entity size_buffer[len];
Efl_Ui_Position_Manager_Size_Batch_Result size_result;
if (pd->size_cache) return;
@ -66,7 +66,7 @@ cache_require(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd)
if (buffer_id == 0)
{
EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->min_size, i, len, NULL, size_buffer) > 0);
BATCH_ACCESS_SIZE(pd->callbacks, i, MIN(len, pd->size - i), EINA_TRUE, size_buffer);
}
size = size_buffer[buffer_id].size;
@ -166,13 +166,14 @@ err:
static inline void
_position_items(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd, Vis_Segment new, int relevant_space_size)
{
int group_id = -1;
Efl_Gfx_Entity *first_group = NULL, *first_fully_visual_group = NULL;
Eina_Size2D first_group_size;
Eina_Rect geom;
const int len = 100;
Efl_Ui_Position_Manager_Batch_Size_Access size_buffer[len];
Efl_Ui_Position_Manager_Batch_Entity_Access obj_buffer[len];
Efl_Ui_Position_Manager_Size_Batch_Entity size_buffer[len];
Efl_Ui_Position_Manager_Size_Batch_Result size_result;
Efl_Ui_Position_Manager_Object_Batch_Entity obj_buffer[len];
Efl_Ui_Position_Manager_Object_Batch_Result object_result;
unsigned int i;
//placement of the plain items
@ -191,20 +192,18 @@ _position_items(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd, Vis_
if (buffer_id == 0)
{
int tmp_group;
int res1, res2;
res1 = _fill_buffer(&pd->object, i, len, &tmp_group, obj_buffer);
res2 = _fill_buffer(&pd->min_size, i, len, NULL, size_buffer);
EINA_SAFETY_ON_FALSE_RETURN(res1 == res2);
EINA_SAFETY_ON_FALSE_RETURN(res2 > 0);
BATCH_ACCESS_SIZE(pd->callbacks, i, len, EINA_FALSE, size_buffer);
BATCH_ACCESS_OBJECT(pd->callbacks, i, len, obj_buffer);
if (i == new.start_id)
{
if (tmp_group > 0)
group_id = tmp_group;
else if (obj_buffer[0].group == EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_GROUP)
group_id = i;
first_group = object_result.group;
first_group_size = size_result.parent_size;
if (obj_buffer[0].depth_leader)
{
first_group = obj_buffer[0].entity;
first_group_size = size_buffer[0].size;
}
}
}
@ -221,7 +220,7 @@ _position_items(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd, Vis_
else
geom.w = size.w;
if (!first_fully_visual_group && obj_buffer[buffer_id].group == EFL_UI_POSITION_MANAGER_BATCH_GROUP_STATE_GROUP &&
if (!first_fully_visual_group && obj_buffer[buffer_id].depth_leader &&
eina_spans_intersect(geom.x, geom.w, pd->viewport.x, pd->viewport.w) &&
eina_spans_intersect(geom.y, geom.h, pd->viewport.y, pd->viewport.h))
{
@ -236,14 +235,6 @@ _position_items(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd, Vis_
geom.x += size.w;
}
//Now place group items
if (group_id > 0)
{
EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->object, group_id, 1, NULL, obj_buffer) == 1);
EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->min_size, group_id, 1, NULL, size_buffer) == 1);
first_group = obj_buffer[0].entity;
first_group_size = size_buffer[0].size;
}
if (pd->dir == EFL_UI_LAYOUT_ORIENTATION_VERTICAL)
first_group_size.w = pd->viewport.w;
else
@ -305,7 +296,7 @@ position_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd)
cur = _search_visual_segment(obj, pd, relevant_space_size, relevant_viewport);
//to performance optimize the whole widget, we are setting the objects that are outside the viewport to visibility false
//The code below ensures that things outside the viewport are always hidden, and things inside the viewport are visible
vis_segment_swap(&pd->object, cur, pd->prev_run);
vis_segment_swap(pd->callbacks, cur, pd->prev_run);
_position_items(obj, pd, cur, relevant_space_size);
@ -342,19 +333,6 @@ schedule_recalc_absolut_size(Eo *obj, Efl_Ui_Position_Manager_List_Data *pd)
eina_future_then(pd->rebuild_absolut_size, _rebuild_job_cb, obj);
}
EOLIAN static void
_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->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;
}
EOLIAN static void
_efl_ui_position_manager_list_efl_ui_position_manager_entity_viewport_set(Eo *obj, Efl_Ui_Position_Manager_List_Data *pd, Eina_Rect size)
{
@ -408,7 +386,8 @@ _efl_ui_position_manager_list_efl_ui_position_manager_entity_position_single_ite
Eina_Size2D space_size;
int relevant_space_size;
Eina_Size2D size;
Efl_Ui_Position_Manager_Batch_Size_Access size_buffer[1];
Efl_Ui_Position_Manager_Size_Batch_Entity size_buffer[1];
Efl_Ui_Position_Manager_Size_Batch_Result size_result;
if (!pd->size) return EINA_RECT(0,0,0,0);
@ -428,7 +407,7 @@ _efl_ui_position_manager_list_efl_ui_position_manager_entity_position_single_ite
geom = pd->viewport;
EINA_SAFETY_ON_FALSE_RETURN_VAL(_fill_buffer(&pd->min_size, idx, 1, NULL, size_buffer) == 1, EINA_RECT_EMPTY());
BATCH_ACCESS_SIZE_VAL(pd->callbacks, idx, 1, EINA_FALSE, size_buffer, EINA_RECT_EMPTY());
size = size_buffer[0].size;
@ -457,7 +436,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->object, pd->prev_run.start_id, pd->prev_run.end_id, EINA_FALSE);
vis_change_segment(pd->callbacks, pd->prev_run.start_id, pd->prev_run.end_id, EINA_FALSE);
pd->prev_run.start_id = 0;
pd->prev_run.end_id = 0;
@ -509,5 +488,24 @@ _efl_ui_position_manager_list_efl_ui_position_manager_entity_relative_item(Eo *o
return new_id;
}
EOLIAN static int
_efl_ui_position_manager_list_efl_ui_position_manager_entity_version(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd EINA_UNUSED, int max EINA_UNUSED)
{
return 1;
}
EOLIAN static void
_efl_ui_position_manager_list_efl_ui_position_manager_data_access_v1_data_access_set(Eo *obj, Efl_Ui_Position_Manager_List_Data *pd, void *obj_access_data, Efl_Ui_Position_Manager_Object_Batch_Callback obj_access, Eina_Free_Cb obj_access_free_cb, void *size_access_data, Efl_Ui_Position_Manager_Size_Batch_Callback size_access, Eina_Free_Cb size_access_free_cb, int size)
{
cache_invalidate(obj, pd);
pd->callbacks.object.data = obj_access_data;
pd->callbacks.object.access = obj_access;
pd->callbacks.object.free_cb = obj_access_free_cb;
pd->callbacks.size.data = size_access_data;
pd->callbacks.size.access = size_access;
pd->callbacks.size.free_cb = size_access_free_cb;
pd->size = size;
}
#include "efl_ui_position_manager_list.eo.c"

View File

@ -1,4 +1,4 @@
class @beta Efl.Ui.Position_Manager.List extends Efl.Object implements Efl.Ui.Position_Manager.Entity
class @beta Efl.Ui.Position_Manager.List extends Efl.Object implements Efl.Ui.Position_Manager.Entity, Efl.Ui.Position_Manager.Data_Access_V1
{
[[Implementation of @Efl.Ui.Position_Manager.Entity for a list
@ -6,7 +6,7 @@ class @beta Efl.Ui.Position_Manager.List extends Efl.Object implements Efl.Ui.Po
]]
implements {
Efl.Object.destructor;
Efl.Ui.Position_Manager.Entity.data_access {set;}
Efl.Ui.Position_Manager.Entity.version;
Efl.Ui.Position_Manager.Entity.viewport {set;}
Efl.Ui.Position_Manager.Entity.scroll_position {set;}
Efl.Ui.Position_Manager.Entity.item_added;
@ -15,5 +15,6 @@ class @beta Efl.Ui.Position_Manager.List extends Efl.Object implements Efl.Ui.Po
Efl.Ui.Position_Manager.Entity.item_size_changed;
Efl.Ui.Position_Manager.Entity.relative_item;
Efl.Ui.Layout_Orientable.orientation {set; get;}
Efl.Ui.Position_Manager.Data_Access_V1.data_access {set;}
}
}

View File

@ -181,6 +181,7 @@ pub_eo_files = [
'efl_ui_selectable.eo',
'efl_ui_multi_selectable.eo',
'efl_ui_single_selectable.eo',
'efl_ui_position_manager_data_access_v1.eo',
]
foreach eo_file : pub_eo_files

View File

@ -25,41 +25,43 @@ item_container_teardown()
win = NULL;
}
static Efl_Ui_Position_Manager_Batch_Result
_size_accessor_get_at(void *data EINA_UNUSED, int start_id, Eina_Rw_Slice memory)
static Efl_Ui_Position_Manager_Size_Batch_Result
_size_accessor_get_at(void *data EINA_UNUSED, Efl_Ui_Position_Manager_Size_Call_Config conf, Eina_Rw_Slice memory)
{
int i;
Efl_Ui_Position_Manager_Batch_Size_Access *sizes = memory.mem;
Efl_Ui_Position_Manager_Batch_Result result;
Efl_Ui_Position_Manager_Size_Batch_Entity *sizes = memory.mem;
Efl_Ui_Position_Manager_Size_Batch_Result result;
for (i = start_id; i < (int)(MIN(start_id + memory.len, eina_inarray_count(arr_size))); ++i)
for (i = conf.range.start_id; i < (int)(MIN(conf.range.end_id, eina_inarray_count(arr_size))); ++i)
{
Eina_Size2D *size = eina_inarray_nth(arr_size, i);
sizes[i - start_id].size = *size;
sizes[i - start_id].group = 0;
sizes[i - conf.range.start_id].size = *size;
sizes[i - conf.range.start_id].depth_leader = 0;
sizes[i - conf.range.start_id].element_depth = 0;
}
result.filled_items = i - start_id;
result.group_id = -1;
result.filled_items = i - conf.range.start_id;
result.parent_size = EINA_SIZE2D(0, 0);
return result;
}
static Efl_Ui_Position_Manager_Batch_Result
_obj_accessor_get_at(void *data EINA_UNUSED, int start_id, Eina_Rw_Slice memory)
static Efl_Ui_Position_Manager_Object_Batch_Result
_obj_accessor_get_at(void *data EINA_UNUSED, Efl_Ui_Position_Manager_Request_Range range, Eina_Rw_Slice memory)
{
int i;
Efl_Ui_Position_Manager_Batch_Entity_Access *objs = memory.mem;
Efl_Ui_Position_Manager_Batch_Result result;
Efl_Ui_Position_Manager_Object_Batch_Entity *objs = memory.mem;
Efl_Ui_Position_Manager_Object_Batch_Result result;
for (i = start_id; i < (int)(MIN(start_id + memory.len, eina_array_count(arr_obj))); ++i)
for (i = range.start_id; i < (int)(MIN(range.end_id, eina_array_count(arr_obj))); ++i)
{
Efl_Gfx_Entity *geom = eina_array_data_get(arr_obj, i);
objs[i - start_id].entity = geom;
objs[i - start_id].group = 0;
objs[i - range.start_id].entity = geom;
objs[i - range.start_id].depth_leader = 0;
objs[i - range.start_id].element_depth = 0;
}
result.filled_items = i - start_id;
result.group_id = -1;
result.filled_items = i - range.start_id;
result.group = NULL;
return result;
}
static void
@ -68,7 +70,7 @@ _initial_setup(void)
arr_obj = eina_array_new(10);
arr_size = eina_inarray_new(sizeof(Eina_Size2D), 10);
efl_ui_position_manager_entity_data_access_set(position_manager,
efl_ui_position_manager_data_access_v1_data_access_set(position_manager,
NULL, _obj_accessor_get_at, NULL,
NULL, _size_accessor_get_at, NULL,
0);