summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorMarcel Hollerbach <mail@marcel-hollerbach.de>2019-07-30 11:13:46 +0200
committerCedric BAIL <cedric.bail@free.fr>2019-07-31 15:51:48 -0700
commitd98d434e56fe98af76cdccc38e96f0e8f34db590 (patch)
treed2cf2c0fa120da17234ec13f642d558cad2528ff /src/lib
parent69975fc72d12dec339f9c0a9b2ce93d34265c599 (diff)
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
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/elementary/efl_ui_collection.c98
-rw-r--r--src/lib/elementary/efl_ui_position_manager_common.h48
-rw-r--r--src/lib/elementary/efl_ui_position_manager_entity.eo26
-rw-r--r--src/lib/elementary/efl_ui_position_manager_grid.c70
-rw-r--r--src/lib/elementary/efl_ui_position_manager_list.c72
5 files changed, 205 insertions, 109 deletions
diff --git a/src/lib/elementary/efl_ui_collection.c b/src/lib/elementary/efl_ui_collection.c
index efc56fc5c6..73ceabd939 100644
--- a/src/lib/elementary/efl_ui_collection.c
+++ b/src/lib/elementary/efl_ui_collection.c
@@ -13,21 +13,20 @@
13#include "elm_priv.h" 13#include "elm_priv.h"
14 14
15typedef struct { 15typedef struct {
16 Eina_Accessor acc;
17 unsigned int last_index; 16 unsigned int last_index;
18 const Eina_List *current; 17 const Eina_List *current;
19 Eina_List **items; 18 Eina_List **items;
20} Fast_Accessor; 19} Fast_Accessor;
21 20
22static Eina_Bool 21static const Eina_List*
23_fast_accessor_get_at(Fast_Accessor *accessor, unsigned int idx, void **data) 22_fast_accessor_get_at(Fast_Accessor *accessor, unsigned int idx)
24{ 23{
25 const Eina_List *over; 24 const Eina_List *over;
26 unsigned int middle; 25 unsigned int middle;
27 unsigned int i; 26 unsigned int i;
28 27
29 if (idx >= eina_list_count(*accessor->items)) 28 if (idx >= eina_list_count(*accessor->items))
30 return EINA_FALSE; 29 return NULL;
31 30
32 if (accessor->last_index == idx) 31 if (accessor->last_index == idx)
33 over = accessor->current; 32 over = accessor->current;
@@ -70,33 +69,12 @@ _fast_accessor_get_at(Fast_Accessor *accessor, unsigned int idx, void **data)
70 } 69 }
71 70
72 if (!over) 71 if (!over)
73 return EINA_FALSE; 72 return NULL;
74 73
75 accessor->last_index = idx; 74 accessor->last_index = idx;
76 accessor->current = over; 75 accessor->current = over;
77 76
78 *data = eina_list_data_get(over); 77 return over;
79 return EINA_TRUE;
80}
81
82
83static Eina_Accessor*
84_fast_accessor_clone(Fast_Accessor *accessor)
85{
86 return eina_list_accessor_new(*accessor->items);
87}
88
89static Eina_List *
90_fast_accessor_get_container(Fast_Accessor *accessor EINA_UNUSED)
91{
92 ERR("Not allowed to get a container!");
93 return NULL;
94}
95
96static void
97_fast_accessor_free(Fast_Accessor *accessor EINA_UNUSED)
98{
99 ERR("Freeing this accessor is not supported");
100} 78}
101 79
102static void 80static void
@@ -105,12 +83,6 @@ _fast_accessor_init(Fast_Accessor *accessor, Eina_List **items)
105 //this is the accessor for accessing the items 83 //this is the accessor for accessing the items
106 //we have to workarround here the problem that 84 //we have to workarround here the problem that
107 //no accessor can be created for a not yet created list. 85 //no accessor can be created for a not yet created list.
108 accessor->acc.version = EINA_ACCESSOR_VERSION;
109 accessor->acc.get_at = FUNC_ACCESSOR_GET_AT(_fast_accessor_get_at);
110 accessor->acc.clone = FUNC_ACCESSOR_CLONE(_fast_accessor_clone);
111 accessor->acc.get_container = FUNC_ACCESSOR_GET_CONTAINER(_fast_accessor_get_container);
112 accessor->acc.free = FUNC_ACCESSOR_FREE(_fast_accessor_free);
113 EINA_MAGIC_SET(&accessor->acc, EINA_MAGIC_ACCESSOR);
114 accessor->items = items; 86 accessor->items = items;
115} 87}
116 88
@@ -285,22 +257,53 @@ _efl_ui_collection_selected_items_get(Eo *obj EINA_UNUSED, Efl_Ui_Collection_Dat
285 return eina_list_iterator_new(pd->selected); 257 return eina_list_iterator_new(pd->selected);
286} 258}
287 259
288static Eina_Bool 260static int
289_size_accessor_get_at(Fast_Accessor *accessor, unsigned int idx, void **data) 261_size_accessor_get_at(void *data, int start_id, Eina_Rw_Slice memory)
290{ 262{
291 Eina_Bool res = EINA_FALSE; 263 Fast_Accessor *accessor = data;
292 Efl_Gfx_Entity *geom; 264 size_t i;
293 Eina_Size2D *size = (void*)data; 265 const Eina_List *lst = _fast_accessor_get_at(accessor, start_id);
294 266
295 res = _fast_accessor_get_at(accessor, idx,(void*) &geom); 267 EINA_SAFETY_ON_NULL_RETURN_VAL(lst, -1);
296 268
297 if (!res) return EINA_FALSE; 269 for (i = 0; i < memory.len; ++i)
298 270 {
299 *size = efl_gfx_hint_size_min_get(geom); 271 Efl_Gfx_Entity *geom = eina_list_data_get(lst);
272 Eina_Size2D size = efl_gfx_hint_size_min_get(geom);
273
274 ((Eina_Size2D*)memory.mem)[i] = size;
275 lst = eina_list_next(lst);
276 if (!lst)
277 {
278 i++;
279 break;
280 }
281 }
300 282
301 return res; 283 return i;
302} 284}
303 285
286static int
287_obj_accessor_get_at(void *data, int start_id, Eina_Rw_Slice memory)
288{
289 Fast_Accessor *accessor = data;
290 size_t i;
291 const Eina_List *lst = _fast_accessor_get_at(accessor, start_id);
292
293 for (i = 0; i < memory.len; ++i)
294 {
295 Efl_Gfx_Entity *geom = eina_list_data_get(lst);
296
297 ((Efl_Gfx_Entity**)memory.mem)[i] = geom;
298 lst = eina_list_next(lst);
299 if (!lst)
300 {
301 i++;
302 break;
303 }
304 }
305 return i;
306}
304 307
305EOLIAN static Efl_Object* 308EOLIAN static Efl_Object*
306_efl_ui_collection_efl_object_constructor(Eo *obj, Efl_Ui_Collection_Data *pd EINA_UNUSED) 309_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
311 314
312 _fast_accessor_init(&pd->obj_accessor, &pd->items); 315 _fast_accessor_init(&pd->obj_accessor, &pd->items);
313 _fast_accessor_init(&pd->size_accessor, &pd->items); 316 _fast_accessor_init(&pd->size_accessor, &pd->items);
314 pd->size_accessor.acc.get_at = FUNC_ACCESSOR_GET_AT(_size_accessor_get_at);
315 317
316 if (!elm_widget_theme_klass_get(obj)) 318 if (!elm_widget_theme_klass_get(obj))
317 elm_widget_theme_klass_set(obj, "item_container"); 319 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
759 if (pd->pos_man) 761 if (pd->pos_man)
760 { 762 {
761 efl_event_callback_array_del(pd->pos_man, pos_manager_cbs(), obj); 763 efl_event_callback_array_del(pd->pos_man, pos_manager_cbs(), obj);
762 efl_ui_position_manager_entity_data_access_set(pd->pos_man, NULL, NULL, 0); 764 efl_ui_position_manager_entity_data_access_set(pd->pos_man, NULL, NULL, NULL, NULL, NULL, NULL, 0);
763 efl_del(pd->pos_man); 765 efl_del(pd->pos_man);
764 } 766 }
765 pd->pos_man = layouter; 767 pd->pos_man = layouter;
@@ -767,7 +769,11 @@ _efl_ui_collection_position_manager_set(Eo *obj, Efl_Ui_Collection_Data *pd, Efl
767 { 769 {
768 efl_parent_set(pd->pos_man, obj); 770 efl_parent_set(pd->pos_man, obj);
769 efl_event_callback_array_add(pd->pos_man, pos_manager_cbs(), obj); 771 efl_event_callback_array_add(pd->pos_man, pos_manager_cbs(), obj);
770 efl_ui_position_manager_entity_data_access_set(pd->pos_man, &pd->obj_accessor.acc, &pd->size_accessor.acc, eina_list_count(pd->items)); 772 //efl_ui_position_manager_entity_data_access_set(pd->pos_man, &pd->obj_accessor.acc, &pd->size_accessor.acc, eina_list_count(pd->items));
773 efl_ui_position_manager_entity_data_access_set(pd->pos_man,
774 &pd->obj_accessor, _obj_accessor_get_at, NULL,
775 &pd->size_accessor, _size_accessor_get_at, NULL,
776 eina_list_count(pd->items));
771 efl_ui_position_manager_entity_viewport_set(pd->pos_man, efl_ui_scrollable_viewport_geometry_get(obj)); 777 efl_ui_position_manager_entity_viewport_set(pd->pos_man, efl_ui_scrollable_viewport_geometry_get(obj));
772 efl_ui_layout_orientation_set(pd->pos_man, pd->dir); 778 efl_ui_layout_orientation_set(pd->pos_man, pd->dir);
773 } 779 }
diff --git a/src/lib/elementary/efl_ui_position_manager_common.h b/src/lib/elementary/efl_ui_position_manager_common.h
new file mode 100644
index 0000000000..56c7eeef08
--- /dev/null
+++ b/src/lib/elementary/efl_ui_position_manager_common.h
@@ -0,0 +1,48 @@
1#ifndef EFL_UI_POSITION_MANAGER_COMMON_H
2#define EFL_UI_POSITION_MANAGER_COMMON_H 1
3
4#include <Eina.h>
5#include <Efl_Ui.h>
6#include "efl_ui_position_manager_entity.eo.h"
7
8typedef struct {
9 void *data;
10 Efl_Ui_Position_Manager_Batch_Access_Entity access; //this can also be the size accessor, but that does not matter here
11 Eina_Free_Cb free_cb;
12} Api_Callback;
13
14static inline int
15_fill_buffer(Api_Callback *cb , int start_id, int len, void *data)
16{
17 Eina_Rw_Slice slice;
18 slice.mem = data;
19 slice.len = len;
20
21 return cb->access(cb->data, start_id, slice);
22}
23
24static inline void
25vis_change_segment(Api_Callback *cb, int a, int b, Eina_Bool flag)
26{
27 const int len = 50;
28 Efl_Gfx_Entity *data[len];
29
30 if (a == b) return;
31
32 for (int i = MIN(a, b); i < MAX(a, b); ++i)
33 {
34 Efl_Gfx_Entity *ent = NULL;
35 int buffer_id = (i-MIN(a,b)) % len;
36
37 if (buffer_id == 0)
38 {
39 EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(cb, MIN(a,b), len, data) >= 0);
40 }
41 ent = data[i - MIN(a,b)];
42 if (ent && !efl_ui_focus_object_focus_get(ent))
43 {
44 efl_gfx_entity_visible_set(ent, flag);
45 }
46 }
47}
48#endif
diff --git a/src/lib/elementary/efl_ui_position_manager_entity.eo b/src/lib/elementary/efl_ui_position_manager_entity.eo
index 471e5d6086..4a65572181 100644
--- a/src/lib/elementary/efl_ui_position_manager_entity.eo
+++ b/src/lib/elementary/efl_ui_position_manager_entity.eo
@@ -1,4 +1,22 @@
1 1
2function Efl.Ui.Position_Manager.Batch_Access_Entity {
3 [[ Function callback for getting a batch of items]]
4 params {
5 start_id : int; [[The id of the first item to fetch]]
6 memory : rw_slice<Efl.Gfx.Entity>; [[The slice to fill the information in, the full slice will be filled if there are enough items]]
7 }
8 return: int; [[The number of filled elements in the slice]]
9};
10
11function Efl.Ui.Position_Manager.Batch_Access_Size {
12 [[ Function callback for getting sizes of a batch of items]]
13 params {
14 start_id : int; [[The id of the first item to fetch]]
15 memory : rw_slice<Efl.Gfx.Entity>; [[The slice to fill the information in, the full slice will be filled if there are enough items]]
16 }
17 return: int; [[The number of filled elements in the slice]]
18};
19
2interface @beta Efl.Ui.Position_Manager.Entity extends Efl.Ui.Layout_Orientable 20interface @beta Efl.Ui.Position_Manager.Entity extends Efl.Ui.Layout_Orientable
3{ 21{
4 [[ 22 [[
@@ -15,14 +33,16 @@ interface @beta Efl.Ui.Position_Manager.Entity extends Efl.Ui.Layout_Orientable
15 33
16 $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). 34 $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).
17 The whole range might need to be traversed in order to calculate the position of all items in some arrangements. 35 The whole range might need to be traversed in order to calculate the position of all items in some arrangements.
36
37 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.
18 ]] 38 ]]
19 set { 39 set {
20 40
21 } 41 }
22 values { 42 values {
23 obj_access : accessor<Efl.Gfx.Entity>; [[The accessor for canvas obejcts, even if the id is valid, the returned object may be NULL]] 43 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]]
24 size_access : accessor<Eina.Size2D>; [[Accessor for the size, returned values are always valid, but might be changed / updated]] 44 size_access : Efl.Ui.Position_Manager.Batch_Access_Size; [[Function callback for the size, returned values are always valid, but might be changed / updated]]
25 size : int; [[valid size for accessors, 0 <= i < size]] 45 size : int; [[valid size for start_id, 0 <= i < size]]
26 } 46 }
27 } 47 }
28 @property viewport { 48 @property viewport {
diff --git a/src/lib/elementary/efl_ui_position_manager_grid.c b/src/lib/elementary/efl_ui_position_manager_grid.c
index 1ae249fca1..2de7ddf896 100644
--- a/src/lib/elementary/efl_ui_position_manager_grid.c
+++ b/src/lib/elementary/efl_ui_position_manager_grid.c
@@ -6,13 +6,14 @@
6#include <Elementary.h> 6#include <Elementary.h>
7#include "elm_widget.h" 7#include "elm_widget.h"
8#include "elm_priv.h" 8#include "elm_priv.h"
9#include "efl_ui_position_manager_common.h"
9 10
10#define MY_CLASS EFL_UI_POSITION_MANAGER_GRID_CLASS 11#define MY_CLASS EFL_UI_POSITION_MANAGER_GRID_CLASS
11#define MY_DATA_GET(obj, pd) \ 12#define MY_DATA_GET(obj, pd) \
12 Efl_Ui_Position_Manager_Grid_Data *pd = efl_data_scope_get(obj, MY_CLASS); 13 Efl_Ui_Position_Manager_Grid_Data *pd = efl_data_scope_get(obj, MY_CLASS);
13 14
14typedef struct { 15typedef struct {
15 Eina_Accessor *content_acc, *size_acc; 16 Api_Callback min_size, object;
16 unsigned int size; 17 unsigned int size;
17 Eina_Rect viewport; 18 Eina_Rect viewport;
18 Eina_Vector2 scroll_position; 19 Eina_Vector2 scroll_position;
@@ -29,27 +30,14 @@ typedef struct {
29 } current_display_table; 30 } current_display_table;
30} Efl_Ui_Position_Manager_Grid_Data; 31} Efl_Ui_Position_Manager_Grid_Data;
31 32
32static inline void
33vis_change_segment(Efl_Ui_Position_Manager_Grid_Data *pd, int a, int b, Eina_Bool flag)
34{
35 for (int i = MIN(a, b); i < MAX(a, b); ++i)
36 {
37 Efl_Gfx_Entity *ent;
38
39 EINA_SAFETY_ON_FALSE_RETURN(eina_accessor_data_get(pd->content_acc, i, (void**) &ent));
40 if (ent && !efl_ui_focus_object_focus_get(ent))
41 {
42 efl_gfx_entity_visible_set(ent, flag);
43 }
44 }
45}
46
47static void 33static void
48_reposition_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd) 34_reposition_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd)
49{ 35{
50 Eina_Size2D space_size; 36 Eina_Size2D space_size;
51 int relevant_space_size, relevant_viewport; 37 int relevant_space_size, relevant_viewport;
52 unsigned int start_id, end_id, step; 38 unsigned int start_id, end_id, step;
39 const int len = 100;
40 Efl_Gfx_Entity *obj_buffer[len];
53 41
54 if (!pd->size) return; 42 if (!pd->size) return;
55 if (pd->max_min_size.w <= 0 || pd->max_min_size.h <= 0) return; 43 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)
83 { 71 {
84 //it is important to first make the segment visible here, and then hide the rest 72 //it is important to first make the segment visible here, and then hide the rest
85 //otherwise we get a state where item_container has 0 subchildren, which triggers a lot of focus logic. 73 //otherwise we get a state where item_container has 0 subchildren, which triggers a lot of focus logic.
86 vis_change_segment(pd, start_id, end_id, EINA_TRUE); 74 vis_change_segment(&pd->object, start_id, end_id, EINA_TRUE);
87 vis_change_segment(pd, pd->prev_run.start_id, pd->prev_run.end_id, EINA_FALSE); 75 vis_change_segment(&pd->object, pd->prev_run.start_id, pd->prev_run.end_id, EINA_FALSE);
88 } 76 }
89 else 77 else
90 { 78 {
91 vis_change_segment(pd, pd->prev_run.start_id, start_id, (pd->prev_run.start_id > start_id)); 79 vis_change_segment(&pd->object, pd->prev_run.start_id, start_id, (pd->prev_run.start_id > start_id));
92 vis_change_segment(pd, pd->prev_run.end_id, end_id, (pd->prev_run.end_id < end_id)); 80 vis_change_segment(&pd->object, pd->prev_run.end_id, end_id, (pd->prev_run.end_id < end_id));
93 } 81 }
94 82
95 for (unsigned int i = start_id; i < end_id; ++i) 83 for (unsigned int i = start_id; i < end_id; ++i)
96 { 84 {
97 Eina_Rect geom; 85 Eina_Rect geom;
98 Efl_Gfx_Entity *ent; 86 Efl_Gfx_Entity *ent;
87 int buffer_id = (i-start_id) % len;
99 geom.size = pd->max_min_size; 88 geom.size = pd->max_min_size;
100 geom.pos = pd->viewport.pos; 89 geom.pos = pd->viewport.pos;
101 90
91 if (buffer_id == 0)
92 {
93 EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->object, i, len, obj_buffer) > 0);
94 }
95
102 if (pd->dir == EFL_UI_LAYOUT_ORIENTATION_VERTICAL) 96 if (pd->dir == EFL_UI_LAYOUT_ORIENTATION_VERTICAL)
103 { 97 {
104 geom.x += pd->max_min_size.w*(i%pd->current_display_table.columns); 98 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)
112 geom.x -= (relevant_space_size); 106 geom.x -= (relevant_space_size);
113 } 107 }
114 108
115 EINA_SAFETY_ON_FALSE_RETURN(eina_accessor_data_get(pd->content_acc, i, (void**) &ent)); 109 ent = ((Efl_Gfx_Entity**)obj_buffer)[buffer_id];
110
116 //printf(">%d (%d, %d, %d, %d) %p\n", i, geom.x, geom.y, geom.w, geom.h, ent); 111 //printf(">%d (%d, %d, %d, %d) %p\n", i, geom.x, geom.y, geom.w, geom.h, ent);
117 efl_gfx_entity_geometry_set(ent, geom); 112 efl_gfx_entity_geometry_set(ent, geom);
118 } 113 }
@@ -170,13 +165,10 @@ _flush_abs_size(Eo *obj, Efl_Ui_Position_Manager_Grid_Data *pd)
170} 165}
171 166
172static inline void 167static inline void
173_update_min_size(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd, int added_index) 168_update_min_size(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd, int added_index EINA_UNUSED, Eina_Size2D min_size)
174{ 169{
175 Eina_Size2D elemsize; 170 pd->max_min_size.w = MAX(pd->max_min_size.w, min_size.w);
176 171 pd->max_min_size.h = MAX(pd->max_min_size.h, min_size.h);
177 EINA_SAFETY_ON_FALSE_RETURN(eina_accessor_data_get(pd->size_acc, added_index, (void*)&elemsize));
178 pd->max_min_size.w = MAX(pd->max_min_size.w, elemsize.w);
179 pd->max_min_size.h = MAX(pd->max_min_size.h, elemsize.h);
180} 172}
181 173
182static inline void 174static inline void
@@ -197,10 +189,14 @@ _flush_min_size(Eo *obj, Efl_Ui_Position_Manager_Grid_Data *pd)
197} 189}
198 190
199EOLIAN static void 191EOLIAN static void
200_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) 192_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)
201{ 193{
202 pd->size_acc = size_access; 194 pd->object.data = obj_access_data;
203 pd->content_acc = obj_access; 195 pd->object.access = obj_access;
196 pd->object.free_cb = obj_access_free_cb;
197 pd->min_size.data = size_access_data;
198 pd->min_size.access = size_access;
199 pd->min_size.free_cb = size_access_free_cb;
204 pd->size = size; 200 pd->size = size;
205} 201}
206 202
@@ -223,10 +219,12 @@ _efl_ui_position_manager_grid_efl_ui_position_manager_entity_scroll_position_set
223EOLIAN static void 219EOLIAN static void
224_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) 220_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)
225{ 221{
222 Eina_Size2D size[1];
226 pd->size ++; 223 pd->size ++;
227 224
228 efl_gfx_entity_visible_set(subobj, EINA_FALSE); 225 efl_gfx_entity_visible_set(subobj, EINA_FALSE);
229 _update_min_size(obj, pd, added_index); 226 EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->min_size, added_index, 1, &size) == 1);
227 _update_min_size(obj, pd, added_index, size[0]);
230 _flush_min_size(obj, pd); 228 _flush_min_size(obj, pd);
231 _flush_abs_size(obj, pd); 229 _flush_abs_size(obj, pd);
232 _reposition_content(obj, pd); //FIXME we might can skip that 230 _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
249EOLIAN static void 247EOLIAN static void
250_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) 248_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)
251{ 249{
250 const int len = 50;
251 Eina_Size2D data[len];
252
252 for (int i = start_id; i <= end_id; ++i) 253 for (int i = start_id; i <= end_id; ++i)
253 { 254 {
254 _update_min_size(obj, pd, i); 255 int buffer_id = (i-start_id) % len;
256 if (buffer_id == 0)
257 {
258 EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->min_size, start_id, len, data) >= 0);
259 }
260 _update_min_size(obj, pd, i, data[i-start_id]);
255 } 261 }
256 262
257 _flush_min_size(obj, pd); 263 _flush_min_size(obj, pd);
diff --git a/src/lib/elementary/efl_ui_position_manager_list.c b/src/lib/elementary/efl_ui_position_manager_list.c
index c793bd3327..4a8497b4bd 100644
--- a/src/lib/elementary/efl_ui_position_manager_list.c
+++ b/src/lib/elementary/efl_ui_position_manager_list.c
@@ -7,13 +7,14 @@
7#include <Elementary.h> 7#include <Elementary.h>
8#include "elm_widget.h" 8#include "elm_widget.h"
9#include "elm_priv.h" 9#include "elm_priv.h"
10#include "efl_ui_position_manager_common.h"
10 11
11#define MY_CLASS EFL_UI_POSITION_MANAGER_LIST_CLASS 12#define MY_CLASS EFL_UI_POSITION_MANAGER_LIST_CLASS
12#define MY_DATA_GET(obj, pd) \ 13#define MY_DATA_GET(obj, pd) \
13 Efl_Ui_Position_Manager_List_Data *pd = efl_data_scope_get(obj, MY_CLASS); 14 Efl_Ui_Position_Manager_List_Data *pd = efl_data_scope_get(obj, MY_CLASS);
14 15
15typedef struct { 16typedef struct {
16 Eina_Accessor *content_acc, *size_acc; 17 Api_Callback min_size, object;
17 unsigned int size; 18 unsigned int size;
18 Eina_Future *rebuild_absolut_size; 19 Eina_Future *rebuild_absolut_size;
19 Eina_Rect viewport; 20 Eina_Rect viewport;
@@ -40,6 +41,9 @@ static void
40cache_require(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd) 41cache_require(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd)
41{ 42{
42 unsigned int i; 43 unsigned int i;
44 const int len = 100;
45 Eina_Size2D size_buffer[100];
46
43 47
44 if (pd->size_cache) return; 48 if (pd->size_cache) return;
45 49
@@ -59,8 +63,14 @@ cache_require(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd)
59 Eina_Size2D size; 63 Eina_Size2D size;
60 int step; 64 int step;
61 int min; 65 int min;
66 int buffer_id = i % len;
67
68 if (buffer_id == 0)
69 {
70 EINA_SAFETY_ON_FALSE_RETURN(_fill_buffer(&pd->min_size, i, len, size_buffer) > 0);
71 }
72 size = size_buffer[buffer_id];
62 73
63 eina_accessor_data_get(pd->size_acc, i, (void**) &size);
64 if (pd->dir == EFL_UI_LAYOUT_ORIENTATION_VERTICAL) 74 if (pd->dir == EFL_UI_LAYOUT_ORIENTATION_VERTICAL)
65 { 75 {
66 step = size.h; 76 step = size.h;
@@ -122,21 +132,6 @@ recalc_absolut_size(Eo *obj, Efl_Ui_Position_Manager_List_Data *pd)
122 efl_event_callback_call(obj, EFL_UI_POSITION_MANAGER_ENTITY_EVENT_CONTENT_MIN_SIZE_CHANGED, &min_size); 132 efl_event_callback_call(obj, EFL_UI_POSITION_MANAGER_ENTITY_EVENT_CONTENT_MIN_SIZE_CHANGED, &min_size);
123} 133}
124 134
125static inline void
126vis_change_segment(Efl_Ui_Position_Manager_List_Data *pd, int a, int b, Eina_Bool flag)
127{
128 for (int i = MIN(a, b); i < MAX(a, b); ++i)
129 {
130 Efl_Gfx_Entity *ent = NULL;
131
132 eina_accessor_data_get(pd->content_acc, i, (void**) &ent);
133 if (ent && !efl_ui_focus_object_focus_get(ent))
134 {
135 efl_gfx_entity_visible_set(ent, flag);
136 }
137 }
138}
139
140static void 135static void
141position_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd) 136position_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd)
142{ 137{
@@ -144,6 +139,9 @@ position_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd)
144 Eina_Size2D space_size; 139 Eina_Size2D space_size;
145 unsigned int start_id = 0, end_id = 0, i; 140 unsigned int start_id = 0, end_id = 0, i;
146 int relevant_space_size, relevant_viewport; 141 int relevant_space_size, relevant_viewport;
142 const int len = 100;
143 Eina_Size2D size_buffer[len];
144 Efl_Gfx_Entity *obj_buffer[len];
147 145
148 if (!pd->size) return; 146 if (!pd->size) return;
149 if (pd->average_item_size <= 0) return; 147 if (pd->average_item_size <= 0) return;
@@ -189,13 +187,13 @@ position_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd)
189 { 187 {
190 //it is important to first make the segment visible here, and then hide the rest 188 //it is important to first make the segment visible here, and then hide the rest
191 //otherwise we get a state where item_container has 0 subchildren, which triggers a lot of focus logic. 189 //otherwise we get a state where item_container has 0 subchildren, which triggers a lot of focus logic.
192 vis_change_segment(pd, start_id, end_id, EINA_TRUE); 190 vis_change_segment(&pd->object, start_id, end_id, EINA_TRUE);
193 vis_change_segment(pd, pd->prev_run.start_id, pd->prev_run.end_id, EINA_FALSE); 191 vis_change_segment(&pd->object, pd->prev_run.start_id, pd->prev_run.end_id, EINA_FALSE);
194 } 192 }
195 else 193 else
196 { 194 {
197 vis_change_segment(pd, pd->prev_run.start_id, start_id, (pd->prev_run.start_id > start_id)); 195 vis_change_segment(&pd->object, pd->prev_run.start_id, start_id, (pd->prev_run.start_id > start_id));
198 vis_change_segment(pd, pd->prev_run.end_id, end_id, (pd->prev_run.end_id < end_id)); 196 vis_change_segment(&pd->object, pd->prev_run.end_id, end_id, (pd->prev_run.end_id < end_id));
199 } 197 }
200 198
201 geom = pd->viewport; 199 geom = pd->viewport;
@@ -209,9 +207,20 @@ position_content(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd)
209 { 207 {
210 Eina_Size2D size; 208 Eina_Size2D size;
211 Efl_Gfx_Entity *ent = NULL; 209 Efl_Gfx_Entity *ent = NULL;
210 int buffer_id = (i-start_id) % len;
212 211
213 EINA_SAFETY_ON_FALSE_RETURN(eina_accessor_data_get(pd->size_acc, i, (void**) &size)); 212 if (buffer_id == 0)
214 EINA_SAFETY_ON_FALSE_RETURN(eina_accessor_data_get(pd->content_acc, i, (void**) &ent)); 213 {
214 int res1, res2;
215
216 res1 = _fill_buffer(&pd->object, i, len, obj_buffer);
217 res2 = _fill_buffer(&pd->min_size, i, len, size_buffer);
218 EINA_SAFETY_ON_FALSE_RETURN(res1 == res2);
219 EINA_SAFETY_ON_FALSE_RETURN(res2 > 0);
220 }
221
222 size = size_buffer[buffer_id];
223 ent = obj_buffer[buffer_id];
215 224
216 if (pd->dir == EFL_UI_LAYOUT_ORIENTATION_VERTICAL) 225 if (pd->dir == EFL_UI_LAYOUT_ORIENTATION_VERTICAL)
217 geom.h = size.h; 226 geom.h = size.h;
@@ -253,11 +262,15 @@ schedule_recalc_absolut_size(Eo *obj, Efl_Ui_Position_Manager_List_Data *pd)
253} 262}
254 263
255EOLIAN static void 264EOLIAN static void
256_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) 265_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)
257{ 266{
258 cache_invalidate(obj, pd); 267 cache_invalidate(obj, pd);
259 pd->content_acc = content_access; 268 pd->object.data = obj_access_data;
260 pd->size_acc = size_access; 269 pd->object.access = obj_access;
270 pd->object.free_cb = obj_access_free_cb;
271 pd->min_size.data = size_access_data;
272 pd->min_size.access = size_access;
273 pd->min_size.free_cb = size_access_free_cb;
261 pd->size = size; 274 pd->size = size;
262} 275}
263 276
@@ -314,6 +327,7 @@ _efl_ui_position_manager_list_efl_ui_position_manager_entity_position_single_ite
314 Eina_Size2D space_size; 327 Eina_Size2D space_size;
315 int relevant_space_size; 328 int relevant_space_size;
316 Eina_Size2D size; 329 Eina_Size2D size;
330 Eina_Size2D size_buffer[1];
317 331
318 if (!pd->size) return EINA_RECT(0,0,0,0); 332 if (!pd->size) return EINA_RECT(0,0,0,0);
319 333
@@ -333,7 +347,9 @@ _efl_ui_position_manager_list_efl_ui_position_manager_entity_position_single_ite
333 347
334 geom = pd->viewport; 348 geom = pd->viewport;
335 349
336 eina_accessor_data_get(pd->size_acc, idx, (void**)&size); 350 EINA_SAFETY_ON_FALSE_RETURN_VAL(_fill_buffer(&pd->min_size, idx, 1, size_buffer) == 1, EINA_RECT_EMPTY());
351
352 size = size_buffer[0];
337 353
338 if (pd->dir == EFL_UI_LAYOUT_ORIENTATION_VERTICAL) 354 if (pd->dir == EFL_UI_LAYOUT_ORIENTATION_VERTICAL)
339 { 355 {
@@ -360,7 +376,7 @@ _efl_ui_position_manager_list_efl_ui_layout_orientable_orientation_set(Eo *obj E
360{ 376{
361 pd->dir = dir; 377 pd->dir = dir;
362 //in order to reset the state of the visible items, just hide everything and set the old segment accordingly 378 //in order to reset the state of the visible items, just hide everything and set the old segment accordingly
363 vis_change_segment(pd, pd->prev_run.start_id, pd->prev_run.end_id, EINA_FALSE); 379 vis_change_segment(&pd->object, pd->prev_run.start_id, pd->prev_run.end_id, EINA_FALSE);
364 pd->prev_run.start_id = 0; 380 pd->prev_run.start_id = 0;
365 pd->prev_run.end_id = 0; 381 pd->prev_run.end_id = 0;
366 382