efl_ui_position_manager: move from accessor to function callback
authorMarcel Hollerbach <mail@marcel-hollerbach.de>
Tue, 30 Jul 2019 09:13:46 +0000 (11:13 +0200)
committerWooHyun Jung <wh0705.jung@samsung.com>
Mon, 5 Aug 2019 02:19:58 +0000 (11:19 +0900)
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

src/lib/elementary/efl_ui_collection.c
src/lib/elementary/efl_ui_position_manager_common.h [new file with mode: 0644]
src/lib/elementary/efl_ui_position_manager_entity.eo
src/lib/elementary/efl_ui_position_manager_grid.c
src/lib/elementary/efl_ui_position_manager_list.c
src/tests/elementary/efl_ui_test_position_manager_common.c

index efc56fc..73ceabd 100644 (file)
 #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;
-
-   *size = efl_gfx_hint_size_min_get(geom);
+   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);
+
+         ((Eina_Size2D*)memory.mem)[i] = size;
+         lst = eina_list_next(lst);
+         if (!lst)
+           {
+              i++;
+              break;
+           }
+     }
 
-   return res;
+   return i;
 }
 
+static int
+_obj_accessor_get_at(void *data, int start_id, Eina_Rw_Slice memory)
+{
+   Fast_Accessor *accessor = data;
+   size_t i;
+   const Eina_List *lst = _fast_accessor_get_at(accessor, start_id);
+
+   for (i = 0; i < memory.len; ++i)
+     {
+         Efl_Gfx_Entity *geom = eina_list_data_get(lst);
+
+         ((Efl_Gfx_Entity**)memory.mem)[i] = geom;
+         lst = eina_list_next(lst);
+         if (!lst)
+           {
+              i++;
+              break;
+           }
+     }
+   return i;
+}
 
 EOLIAN static Efl_Object*
 _efl_ui_collection_efl_object_constructor(Eo *obj, Efl_Ui_Collection_Data *pd EINA_UNUSED)
@@ -311,7 +314,6 @@ _efl_ui_collection_efl_object_constructor(Eo *obj, Efl_Ui_Collection_Data *pd EI
 
    _fast_accessor_init(&pd->obj_accessor, &pd->items);
    _fast_accessor_init(&pd->size_accessor, &pd->items);
-   pd->size_accessor.acc.get_at = FUNC_ACCESSOR_GET_AT(_size_accessor_get_at);
 
    if (!elm_widget_theme_klass_get(obj))
      elm_widget_theme_klass_set(obj, "item_container");
@@ -759,7 +761,7 @@ _efl_ui_collection_position_manager_set(Eo *obj, Efl_Ui_Collection_Data *pd, Efl
    if (pd->pos_man)
      {
         efl_event_callback_array_del(pd->pos_man, pos_manager_cbs(), obj);
-        efl_ui_position_manager_entity_data_access_set(pd->pos_man, NULL, NULL, 0);
+        efl_ui_position_manager_entity_data_access_set(pd->pos_man, NULL, NULL, NULL, NULL, NULL, NULL, 0);
         efl_del(pd->pos_man);
      }
    pd->pos_man = layouter;
@@ -767,7 +769,11 @@ _efl_ui_collection_position_manager_set(Eo *obj, Efl_Ui_Collection_Data *pd, Efl
      {
         efl_parent_set(pd->pos_man, obj);
         efl_event_callback_array_add(pd->pos_man, pos_manager_cbs(), obj);
-        efl_ui_position_manager_entity_data_access_set(pd->pos_man, &pd->obj_accessor.acc, &pd->size_accessor.acc, eina_list_count(pd->items));
+        //efl_ui_position_manager_entity_data_access_set(pd->pos_man, &pd->obj_accessor.acc, &pd->size_accessor.acc, eina_list_count(pd->items));
+        efl_ui_position_manager_entity_data_access_set(pd->pos_man,
+          &pd->obj_accessor, _obj_accessor_get_at, NULL,
+          &pd->size_accessor, _size_accessor_get_at, NULL,
+          eina_list_count(pd->items));
         efl_ui_position_manager_entity_viewport_set(pd->pos_man, efl_ui_scrollable_viewport_geometry_get(obj));
         efl_ui_layout_orientation_set(pd->pos_man, pd->dir);
      }
diff --git a/src/lib/elementary/efl_ui_position_manager_common.h b/src/lib/elementary/efl_ui_position_manager_common.h
new file mode 100644 (file)
index 0000000..56c7eee
--- /dev/null
@@ -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
index 471e5d6..4a65572 100644 (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 {
index 1ae249f..2de7ddf 100644 (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);
index c793bd3..4a8497b 100644 (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;
 
index 7cf39f9..ea89662 100644 (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);
 
-static void
-_free_cb(Eina_Accessor *it EINA_UNUSED)
-{
-   eina_accessor_free(size_acc);
+         ((Eina_Size2D*)memory.mem)[i - start_id] = *size;
+     }
+   return i - start_id;
 }
 
-static Eina_Bool
-_lock_cb(Eina_Accessor *it EINA_UNUSED)
+static int
+_obj_accessor_get_at(void *data EINA_UNUSED, int start_id, Eina_Rw_Slice memory)
 {
-   return eina_accessor_lock(size_acc);
-}
+   int i;
 
-static Eina_Accessor*
-_clone_cb(Eina_Accessor *it EINA_UNUSED)
-{
-   return eina_accessor_clone(size_acc);
-}
+   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 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