1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 
5 #include <fnmatch.h>
6 
7 #define EFL_ACCESS_OBJECT_PROTECTED
8 #define EFL_ACCESS_SELECTION_PROTECTED
9 #define EFL_ACCESS_WIDGET_ACTION_PROTECTED
10 #define ELM_WIDGET_ITEM_PROTECTED
11 #define EFL_UI_FOCUS_COMPOSITION_PROTECTED
12 
13 #include <Elementary.h>
14 #include <Elementary_Cursor.h>
15 
16 #include "elm_priv.h"
17 #include "elm_widget_genlist.h"
18 #include "elm_interface_scrollable.h"
19 #include "elm_pan_eo.h"
20 #include "efl_ui_focus_parent_provider_gen_eo.h"
21 #include "efl_ui_focus_composition_adapter.eo.h"
22 #include "elm_genlist_item_eo.h"
23 #include "elm_genlist_pan_eo.h"
24 #include "elm_genlist_eo.h"
25 
26 #define MY_PAN_CLASS ELM_GENLIST_PAN_CLASS
27 
28 #define MY_PAN_CLASS_NAME "Elm_Genlist_Pan"
29 #define MY_PAN_CLASS_NAME_LEGACY "elm_genlist_pan"
30 
31 #define MY_CLASS ELM_GENLIST_CLASS
32 
33 #define MY_CLASS_NAME "Elm_Genlist"
34 #define MY_CLASS_NAME_LEGACY "elm_genlist"
35 
36 // internally allocated
37 #define CLASS_ALLOCATED     0x3a70f11f
38 
39 #define MAX_ITEMS_PER_BLOCK 32
40 #define REORDER_EFFECT_TIME 0.5
41 #define MULTI_DOWN_TIME 1.0
42 #define SWIPE_TIME 0.4
43 #define SCR_HOLD_TIME 0.1
44 #define ITEM_QUEUE_MAX 128
45 
46 #define ERR_ABORT(_msg)                         \
47    do {                                         \
48         ERR(_msg);                              \
49         if (getenv("ELM_ERROR_ABORT")) abort(); \
50    } while (0)
51 
52 #define ELM_PRIV_GENLIST_SIGNALS(cmd) \
53     cmd(SIG_ACTIVATED, "activated", "") \
54     cmd(SIG_CLICKED_DOUBLE, "clicked,double", "") \
55     cmd(SIG_CLICKED_RIGHT, "clicked,right", "") \
56     cmd(SIG_SELECTED, "selected", "") \
57     cmd(SIG_UNSELECTED, "unselected", "") \
58     cmd(SIG_EXPANDED, "expanded", "") \
59     cmd(SIG_CONTRACTED, "contracted", "") \
60     cmd(SIG_EXPAND_REQUEST, "expand,request", "") \
61     cmd(SIG_CONTRACT_REQUEST, "contract,request", "") \
62     cmd(SIG_REALIZED, "realized", "") \
63     cmd(SIG_UNREALIZED, "unrealized", "") \
64     cmd(SIG_DRAG_START_UP, "drag,start,up", "") \
65     cmd(SIG_DRAG_START_DOWN, "drag,start,down", "") \
66     cmd(SIG_DRAG_START_LEFT, "drag,start,left", "") \
67     cmd(SIG_DRAG_START_RIGHT, "drag,start,right", "") \
68     cmd(SIG_DRAG_STOP, "drag,stop", "") \
69     cmd(SIG_DRAG, "drag", "") \
70     cmd(SIG_LONGPRESSED, "longpressed", "") \
71     cmd(SIG_SCROLL, "scroll", "") \
72     cmd(SIG_SCROLL_ANIM_START, "scroll,anim,start", "") \
73     cmd(SIG_SCROLL_ANIM_STOP, "scroll,anim,stop", "") \
74     cmd(SIG_SCROLL_DRAG_START, "scroll,drag,start", "") \
75     cmd(SIG_SCROLL_DRAG_STOP, "scroll,drag,stop", "") \
76     cmd(SIG_EDGE_TOP, "edge,top", "") \
77     cmd(SIG_EDGE_BOTTOM, "edge,bottom", "") \
78     cmd(SIG_EDGE_LEFT, "edge,left", "") \
79     cmd(SIG_EDGE_RIGHT, "edge,right", "") \
80     cmd(SIG_VBAR_DRAG, "vbar,drag", "") \
81     cmd(SIG_VBAR_PRESS, "vbar,press", "") \
82     cmd(SIG_VBAR_UNPRESS, "vbar,unpress", "") \
83     cmd(SIG_HBAR_DRAG, "hbar,drag", "") \
84     cmd(SIG_HBAR_PRESS, "hbar,press", "") \
85     cmd(SIG_HBAR_UNPRESS, "hbar,unpress", "") \
86     cmd(SIG_MULTI_SWIPE_LEFT, "multi,swipe,left", "") \
87     cmd(SIG_MULTI_SWIPE_RIGHT, "multi,swipe,right", "") \
88     cmd(SIG_MULTI_SWIPE_UP, "multi,swipe,up", "") \
89     cmd(SIG_MULTI_SWIPE_DOWN, "multi,swipe,down", "") \
90     cmd(SIG_MULTI_PINCH_OUT, "multi,pinch,out", "") \
91     cmd(SIG_MULTI_PINCH_IN, "multi,pinch,in", "") \
92     cmd(SIG_SWIPE, "swipe", "") \
93     cmd(SIG_MOVED, "moved", "") \
94     cmd(SIG_MOVED_AFTER, "moved,after", "") \
95     cmd(SIG_MOVED_BEFORE, "moved,before", "") \
96     cmd(SIG_INDEX_UPDATE, "index,update", "") \
97     cmd(SIG_TREE_EFFECT_FINISHED , "tree,effect,finished", "") \
98     cmd(SIG_HIGHLIGHTED, "highlighted", "") \
99     cmd(SIG_UNHIGHLIGHTED, "unhighlighted", "") \
100     cmd(SIG_ITEM_FOCUSED, "item,focused", "") \
101     cmd(SIG_ITEM_UNFOCUSED, "item,unfocused", "") \
102     cmd(SIG_PRESSED, "pressed", "") \
103     cmd(SIG_RELEASED, "released", "") \
104     cmd(SIG_FILTER_DONE, "filter,done", "")
105 
106 ELM_PRIV_GENLIST_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE);
107 
108 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
109    ELM_PRIV_GENLIST_SIGNALS(ELM_PRIV_SMART_CALLBACKS_DESC)
110    {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
111    {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
112    {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
113    {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
114 
115    {NULL, NULL}
116 };
117 #undef ELM_PRIV_GENLIST_SIGNALS
118 
119 /* edje signals internally used */
120 static const char SIGNAL_ENABLED[] = "elm,state,enabled";
121 static const char SIGNAL_DISABLED[] = "elm,state,disabled";
122 static const char SIGNAL_SELECTED[] = "elm,state,selected";
123 static const char SIGNAL_UNSELECTED[] = "elm,state,unselected";
124 static const char SIGNAL_EXPANDED[] = "elm,state,expanded";
125 static const char SIGNAL_CONTRACTED[] = "elm,state,contracted";
126 static const char SIGNAL_FLIP_ENABLED[] = "elm,state,flip,enabled";
127 static const char SIGNAL_FLIP_DISABLED[] = "elm,state,flip,disabled";
128 static const char SIGNAL_DECORATE_ENABLED[] = "elm,state,decorate,enabled";
129 static const char SIGNAL_DECORATE_DISABLED[] = "elm,state,decorate,disabled";
130 static const char SIGNAL_DECORATE_ENABLED_EFFECT[] = "elm,state,decorate,enabled,effect";
131 static const char SIGNAL_REORDER_ENABLED[] = "elm,state,reorder,enabled";
132 static const char SIGNAL_REORDER_DISABLED[] = "elm,state,reorder,disabled";
133 static const char SIGNAL_REORDER_MODE_SET[] = "elm,state,reorder,mode_set";
134 static const char SIGNAL_REORDER_MODE_UNSET[] = "elm,state,reorder,mode_unset";
135 static const char SIGNAL_CONTRACT_FLIP[] = "elm,state,contract_flip";
136 static const char SIGNAL_SHOW[] = "elm,state,show";
137 static const char SIGNAL_HIDE[] = "elm,state,hide";
138 static const char SIGNAL_FLIP_ITEM[] = "elm,action,flip_item";
139 static const char SIGNAL_ODD[] = "elm,state,odd";
140 static const char SIGNAL_EVEN[] = "elm,state,even";
141 static const char SIGNAL_FOCUSED[] = "elm,state,focused";
142 static const char SIGNAL_UNFOCUSED[] = "elm,state,unfocused";
143 static const char SIGNAL_LIST_SINGLE[] = "elm,state,list,single";
144 static const char SIGNAL_LIST_FIRST[] = "elm,state,list,first";
145 static const char SIGNAL_LIST_LAST[] = "elm,state,list,last";
146 static const char SIGNAL_LIST_MIDDLE[] = "elm,state,list,middle";
147 static const char SIGNAL_GROUP_SINGLE[] = "elm,state,group,single";
148 static const char SIGNAL_GROUP_FIRST[] = "elm,state,group,first";
149 static const char SIGNAL_GROUP_LAST[] = "elm,state,group,last";
150 static const char SIGNAL_GROUP_MIDDLE[] = "elm,state,group,middle";
151 
152 static void _item_unrealize(Elm_Gen_Item *it);
153 static Eina_Bool _item_select(Elm_Gen_Item *it);
154 static void _item_unselect(Elm_Gen_Item *it);
155 static void _item_highlight(Elm_Gen_Item *it);
156 static Eina_Bool _key_action_move(Evas_Object *obj, const char *params);
157 static Eina_Bool _key_action_select(Evas_Object *obj, const char *params);
158 static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params);
159 static void  _calc_job(void *data);
160 static void  _update_job(void *data);
161 static Eina_Bool _item_block_recalc(Item_Block *itb, int in, Eina_Bool qadd);
162 static void _item_mouse_callbacks_add(Elm_Gen_Item *it, Evas_Object *view);
163 static void _item_mouse_callbacks_del(Elm_Gen_Item *it, Evas_Object *view);
164 static void _access_activate_cb(void *data EINA_UNUSED,
165                                 Evas_Object *part_obj EINA_UNUSED,
166                                 Elm_Object_Item *item);
167 static void _decorate_item_set(Elm_Gen_Item *);
168 static void _internal_elm_genlist_clear(Evas_Object *obj);
169 static Eina_Bool _item_filtered_get(Elm_Gen_Item *it, Elm_Genlist_Data *sd);
170 
171 static void _elm_genlist_tree_effect_stop(Elm_Genlist_Data *sd);
172 static Eina_Bool _elm_genlist_tree_effect_setup(Elm_Genlist_Data *sd);
173 
174 static void _item_expanded_set_noevent(Elm_Gen_Item *it, Eina_Bool expanded);
175 
176 static Eina_Bool _item_process(Elm_Genlist_Data *sd, Elm_Gen_Item *it);
177 static void _item_process_post(Elm_Genlist_Data *sd, Elm_Gen_Item *it);
178 
179 static const Elm_Action key_actions[] = {
180    {"move", _key_action_move},
181    {"select", _key_action_select},
182    {"escape", _key_action_escape},
183    {NULL, NULL}
184 };
185 
186 static void
_size_cache_free(void * data)187 _size_cache_free(void *data)
188 {
189    if(data) free(data);
190 }
191 
192 static Eina_Bool
_is_no_select(Elm_Gen_Item * it)193 _is_no_select(Elm_Gen_Item *it)
194 {
195    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
196 
197    if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
198        (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY) ||
199        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
200        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
201      return EINA_TRUE;
202    return EINA_FALSE;
203 }
204 
205 EOLIAN static void
_elm_genlist_pan_elm_pan_pos_set(Eo * obj,Elm_Genlist_Pan_Data * psd,Evas_Coord x,Evas_Coord y)206 _elm_genlist_pan_elm_pan_pos_set(Eo *obj, Elm_Genlist_Pan_Data *psd, Evas_Coord x, Evas_Coord y)
207 {
208    Item_Block *itb;
209 
210    Elm_Genlist_Data *sd = psd->wsd;
211 
212    if ((x == sd->pan_x) && (y == sd->pan_y)) return;
213    sd->pan_x = x;
214    sd->pan_y = y;
215 
216    EINA_INLIST_FOREACH(sd->blocks, itb)
217      {
218         if ((itb->y + itb->h) > y)
219           {
220              Elm_Gen_Item *it;
221              Eina_List *l2;
222 
223              EINA_LIST_FOREACH(itb->items, l2, it)
224                {
225                   if ((itb->y + it->y) >= y)
226                     {
227                        sd->anchor_item = it;
228                        sd->anchor_y = -(itb->y + it->y - y);
229                        goto done;
230                     }
231                }
232           }
233      }
234 done:
235    if (!sd->reorder_move_animator) evas_object_smart_changed(obj);
236 }
237 
238 EOLIAN static void
_elm_genlist_pan_elm_pan_pos_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Pan_Data * psd,Evas_Coord * x,Evas_Coord * y)239 _elm_genlist_pan_elm_pan_pos_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Pan_Data *psd, Evas_Coord *x, Evas_Coord *y)
240 {
241    if (x) *x = psd->wsd->pan_x;
242    if (y) *y = psd->wsd->pan_y;
243 }
244 
245 EOLIAN static void
_elm_genlist_pan_elm_pan_pos_max_get(const Eo * obj,Elm_Genlist_Pan_Data * psd,Evas_Coord * x,Evas_Coord * y)246 _elm_genlist_pan_elm_pan_pos_max_get(const Eo *obj, Elm_Genlist_Pan_Data *psd, Evas_Coord *x, Evas_Coord *y)
247 {
248    Evas_Coord ow, oh;
249 
250    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
251    ow = psd->wsd->minw - ow;
252    if (ow < 0) ow = 0;
253    oh = psd->wsd->minh - oh;
254    if (oh < 0) oh = 0;
255    if (x) *x = ow;
256    if (y) *y = oh;
257 }
258 
259 EOLIAN static void
_elm_genlist_pan_elm_pan_pos_min_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Pan_Data * _pd EINA_UNUSED,Evas_Coord * x,Evas_Coord * y)260 _elm_genlist_pan_elm_pan_pos_min_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Pan_Data *_pd EINA_UNUSED, Evas_Coord *x, Evas_Coord *y)
261 {
262    if (x) *x = 0;
263    if (y) *y = 0;
264 }
265 
266 EOLIAN static void
_elm_genlist_pan_elm_pan_content_size_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Pan_Data * psd,Evas_Coord * w,Evas_Coord * h)267 _elm_genlist_pan_elm_pan_content_size_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Pan_Data *psd, Evas_Coord *w, Evas_Coord *h)
268 {
269    if (w) *w = psd->wsd->minw;
270    if (h) *h = psd->wsd->minh;
271 }
272 
273 EOLIAN static void
_elm_genlist_pan_efl_canvas_group_group_del(Eo * obj,Elm_Genlist_Pan_Data * psd)274 _elm_genlist_pan_efl_canvas_group_group_del(Eo *obj, Elm_Genlist_Pan_Data *psd)
275 {
276    ecore_job_del(psd->resize_job);
277 
278    efl_canvas_group_del(efl_super(obj, MY_PAN_CLASS));
279 }
280 
281 EOLIAN static void
_elm_genlist_pan_efl_gfx_entity_position_set(Eo * obj,Elm_Genlist_Pan_Data * psd,Eina_Position2D pos)282 _elm_genlist_pan_efl_gfx_entity_position_set(Eo *obj, Elm_Genlist_Pan_Data *psd, Eina_Position2D pos)
283 {
284    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y))
285      return;
286 
287    efl_gfx_entity_position_set(efl_super(obj, MY_PAN_CLASS), pos);
288 
289    psd->wsd->pan_changed = EINA_TRUE;
290    evas_object_smart_changed(obj);
291 }
292 
293 static void
_elm_genlist_pan_smart_resize_job(void * data)294 _elm_genlist_pan_smart_resize_job(void *data)
295 {
296    ELM_GENLIST_PAN_DATA_GET(data, psd);
297 
298    elm_layout_sizing_eval(psd->wobj);
299    psd->resize_job = NULL;
300 }
301 
302 EOLIAN static void
_elm_genlist_pan_efl_gfx_entity_size_set(Eo * obj,Elm_Genlist_Pan_Data * psd,Eina_Size2D size)303 _elm_genlist_pan_efl_gfx_entity_size_set(Eo *obj, Elm_Genlist_Pan_Data *psd, Eina_Size2D size)
304 {
305    Elm_Genlist_Data *sd = psd->wsd;
306    Eina_Size2D old;
307 
308    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, size.w, size.h))
309      return;
310 
311    old = efl_gfx_entity_size_get(obj);
312    if ((old.w == size.w) && (old.h == size.h)) goto super; // should already be intercepted above
313    if ((sd->mode == ELM_LIST_COMPRESS) && (old.w != size.w))
314      {
315         /* fix me later */
316         ecore_job_del(psd->resize_job);
317         psd->resize_job =
318           ecore_job_add(_elm_genlist_pan_smart_resize_job, obj);
319      }
320    sd->pan_changed = EINA_TRUE;
321    evas_object_smart_changed(obj);
322    // if the width changed we may have to resize content if scrollbar went
323    // away or appeared to queue a job to deal with it. it should settle in
324    // the end to a steady-state
325    if (old.w != size.w)
326      efl_canvas_group_change(sd->obj);
327 
328 super:
329    efl_gfx_entity_size_set(efl_super(obj, MY_PAN_CLASS), size);
330 }
331 
332 static void
_item_text_realize(Elm_Gen_Item * it,Evas_Object * target,Eina_List ** source,const char * parts)333 _item_text_realize(Elm_Gen_Item *it,
334                    Evas_Object *target,
335                    Eina_List **source,
336                    const char *parts)
337 {
338    const Eina_List *l;
339    const char *key;
340    char *s;
341    char buf[256];
342 
343    if (!it->itc->func.text_get) return;
344 
345    if (!(*source))
346      *source = elm_widget_stringlist_get
347         (edje_object_data_get(target, "texts"));
348    EINA_LIST_FOREACH(*source, l, key)
349      {
350         if (parts && fnmatch(parts, key, FNM_PERIOD)) continue;
351 
352         s = it->itc->func.text_get
353            ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
354         if (s)
355           {
356              edje_object_part_text_escaped_set(target, key, s);
357              free(s);
358 
359              snprintf(buf, sizeof(buf), "elm,state,%s,visible", key);
360              edje_object_signal_emit(target, buf, "elm");
361           }
362         else
363           {
364              edje_object_part_text_set(target, key, "");
365           }
366         if (_elm_config->atspi_mode)
367           efl_access_i18n_name_changed_signal_emit(EO_OBJ(it));
368      }
369 }
370 
371 static void
_widget_calculate_recursive(Eo * obj)372 _widget_calculate_recursive(Eo *obj)
373 {
374    Elm_Widget_Smart_Data *pd = NULL;
375    Evas_Object *child;
376 
377    if (!efl_isa(obj, EFL_UI_WIDGET_CLASS)) return;
378 
379    pd = efl_data_scope_get(obj, EFL_UI_WIDGET_CLASS);
380    if (!pd || !pd->resize_obj)
381      return;
382 
383    if (!efl_canvas_group_need_recalculate_get(obj))
384      {
385         if (!efl_isa(pd->resize_obj, EFL_CANVAS_GROUP_CLASS) ||
386             !efl_canvas_group_need_recalculate_get(pd->resize_obj))
387           return;
388      }
389 
390    for (unsigned int i = 0; i < eina_array_count(pd->children); ++i)
391      {
392         child = eina_array_data_get(pd->children, i);
393         _widget_calculate_recursive(child);
394      }
395 
396    efl_canvas_group_calculate(obj);
397 }
398 
399 static void
_item_content_realize(Elm_Gen_Item * it,Evas_Object * target,Eina_List ** contents,const char * src,const char * parts,Eina_Bool calc)400 _item_content_realize(Elm_Gen_Item *it,
401                       Evas_Object *target,
402                       Eina_List **contents,
403                       const char *src,
404                       const char *parts,
405                       Eina_Bool calc)
406 {
407    Evas_Object *content;
408    char buf[256];
409    Eina_List *source;
410    const char *key;
411 
412    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
413 
414    if (!parts)
415      {
416         EINA_LIST_FREE(*contents, content)
417           evas_object_del(content);
418      }
419    if ((!it->itc->func.content_get) &&
420       ((it->itc->version < 3) || (!it->itc->func.reusable_content_get))) return;
421 
422    source = elm_widget_stringlist_get(edje_object_data_get(target, src));
423 
424    EINA_LIST_FREE(source, key)
425      {
426         if (parts && fnmatch(parts, key, FNM_PERIOD))
427           continue;
428 
429         Evas_Object *old = NULL;
430         old = edje_object_part_swallow_get(target, key);
431 
432         // Reuse content by popping from the cache
433         content = NULL;
434         if (it->itc->func.reusable_content_get)
435           content = it->itc->func.reusable_content_get(
436              (void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key, old);
437         if (!content)
438           {
439              // Call the content get
440              if (it->itc->func.content_get)
441                content = it->itc->func.content_get
442                   ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
443              if (!content) goto out;
444           }
445 
446         if (content != old)
447           {
448              eina_hash_add(sd->content_item_map, &content, it->base->eo_obj);
449              // FIXME: Genlist item doesn't update its size when the size of
450              // content is changed, so deferred calculation for content should
451              // be performed before realization.
452              if (efl_isa(content, EFL_UI_WIDGET_CLASS))
453                {
454                   ELM_WIDGET_DATA_GET_OR_RETURN(content, wd);
455 
456                   // FIXME : Layout need sizing eval before group calculate
457                   if (efl_class_get(content) == EFL_UI_LAYOUT_BASE_CLASS)
458                     elm_layout_sizing_eval(content);
459 
460                   _widget_calculate_recursive(content);
461                }
462 
463              if (!edje_object_part_swallow(target, key, content))
464                {
465                   ERR("%s (%p) can not be swallowed into %s",
466                       evas_object_type_get(content), content, key);
467                   evas_object_del(content);
468                   goto out;
469                }
470              elm_widget_sub_object_add(WIDGET(it), content);
471 
472              if (elm_widget_is(content))
473                {
474                   elm_widget_tree_unfocusable_set(content, it->item->unfocusable);
475                   if (!calc && (!it->item->unfocusable))
476                     _elm_widget_full_eval(content);
477                }
478           }
479         *contents = eina_list_append(*contents, content);
480 
481         if (elm_wdg_item_disabled_get(EO_OBJ(it)))
482           elm_widget_disabled_set(content, EINA_TRUE);
483 
484         snprintf(buf, sizeof(buf), "elm,state,%s,visible", key);
485         edje_object_signal_emit(target, buf, "elm");
486 out:
487         if (old && content != old)
488           {
489              *contents = eina_list_remove(*contents, old);
490              evas_object_del(old);
491              eina_hash_del_by_key(sd->content_item_map, &old);
492           }
493      }
494 }
495 
496 static void
_item_state_realize(Elm_Gen_Item * it,Evas_Object * target,const char * parts)497 _item_state_realize(Elm_Gen_Item *it, Evas_Object *target, const char *parts)
498 {
499    Eina_List *src;
500    const char *key;
501    char buf[4096];
502 
503    if (!it->itc->func.state_get) return;
504 
505    src = elm_widget_stringlist_get(edje_object_data_get(target, "states"));
506    EINA_LIST_FREE(src, key)
507      {
508         if (parts && fnmatch(parts, key, FNM_PERIOD)) continue;
509 
510         Eina_Bool on = it->itc->func.state_get
511            ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
512 
513         if (on)
514           {
515              snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
516              edje_object_signal_emit(target, buf, "elm");
517           }
518         else
519           {
520              snprintf(buf, sizeof(buf), "elm,state,%s,passive", key);
521              edje_object_signal_emit(target, buf, "elm");
522           }
523      }
524    edje_object_message_signal_process(target);
525 }
526 
527 /**
528  * Apply the right style for the created item view.
529  */
530 static void
_view_style_update(Elm_Gen_Item * it,Evas_Object * view,const char * style)531 _view_style_update(Elm_Gen_Item *it, Evas_Object *view, const char *style)
532 {
533    char buf[1024];
534    const char *stacking_even;
535    const char *stacking;
536    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
537 
538    // FIXME:  There exists
539    // item, item_compress, item_odd, item_compress_odd,
540    // tree, tree_compress, tree_odd, tree_odd_compress
541    // But those used case by case. :-(
542    // Anyway, belows codes are for backward..
543    if (it->decorate_it_set)
544      {
545         // item, item_compress, item_odd, item_compress_odd
546         strncpy(buf, "item", sizeof(buf));
547         if (sd->mode == ELM_LIST_COMPRESS)
548            strncat(buf, "_compress", sizeof(buf) - strlen(buf) - 1);
549 
550         if (it->item->order_num_in & 0x1)
551            strncat(buf, "_odd", sizeof(buf) - strlen(buf) - 1);
552         strncat(buf, "/", sizeof(buf) - strlen(buf) - 1);
553         strncat(buf, style, sizeof(buf) - strlen(buf) - 1);
554      }
555    else
556      {
557         // item, item_compress, tree, tree_compress
558         if (it->item->type & ELM_GENLIST_ITEM_TREE)
559            snprintf(buf, sizeof(buf), "tree%s/%s",
560                     sd->mode == ELM_LIST_COMPRESS ? "_compress" :
561                     "", style ? : "default");
562         else
563            snprintf(buf, sizeof(buf), "item%s/%s",
564                     sd->mode == ELM_LIST_COMPRESS ? "_compress" :
565                     "",style ? : "default");
566      }
567 
568    Eina_Error th_ret =
569       elm_widget_theme_object_set(WIDGET(it), view, "genlist", buf,
570                                   elm_widget_style_get(WIDGET(it)));
571    if (th_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC)
572      {
573         ERR("%s is not a valid genlist item style. "
574             "Automatically falls back into default style.",
575             style);
576         elm_widget_theme_object_set
577           (WIDGET(it), view, "genlist", "item/default", "default");
578      }
579 
580    edje_object_mirrored_set(view, efl_ui_mirrored_get(WIDGET(it)));
581    edje_object_scale_set(view, efl_gfx_entity_scale_get(WIDGET(it))
582                          * elm_config_scale_get());
583 
584    stacking_even = edje_object_data_get(view, "stacking_even");
585    if (!stacking_even) stacking_even = "above";
586    it->item->stacking_even = !!strcmp("above", stacking_even);
587 
588    stacking = edje_object_data_get(view, "stacking");
589    if (!stacking) stacking = "yes";
590    it->item->nostacking = !!strcmp("yes", stacking);
591 }
592 
593 /**
594  * Create a VIEW(it) during _item_realize()
595  */
596 static Evas_Object *
_view_create(Elm_Gen_Item * it,const char * style)597 _view_create(Elm_Gen_Item *it, const char *style)
598 {
599    Evas_Object *view = edje_object_add(evas_object_evas_get(WIDGET(it)));
600    evas_object_smart_member_add(view, it->item->wsd->pan_obj);
601    elm_widget_sub_object_add(WIDGET(it), view);
602    edje_object_scale_set(view, efl_gfx_entity_scale_get(WIDGET(it)) *
603                          elm_config_scale_get());
604 
605    _view_style_update(it, view, style);
606    return view;
607 }
608 
609 static void
_view_clear(Evas_Object * view,Eina_List ** texts,Eina_List ** contents)610 _view_clear(Evas_Object *view, Eina_List **texts, Eina_List **contents)
611 {
612    const char *part;
613    Evas_Object *c;
614    const Eina_List *l;
615 
616    EINA_LIST_FOREACH(*texts, l, part)
617      edje_object_part_text_set(view, part, NULL);
618    ELM_SAFE_FREE(*texts, elm_widget_stringlist_free);
619 
620    if (contents)
621      {
622         EINA_LIST_FREE(*contents, c)
623            evas_object_del(c);
624      }
625 }
626 
627 static void
_item_scroll(Elm_Genlist_Data * sd)628 _item_scroll(Elm_Genlist_Data *sd)
629 {
630    Evas_Coord gith = 0;
631    Elm_Gen_Item *it = NULL;
632    Evas_Coord ow, oh, dx = 0, dy = 0, dw = 0, dh = 0;
633 
634    if (!sd->show_item) return;
635 
636    evas_object_geometry_get(sd->pan_obj, NULL, NULL, &ow, &oh);
637    it = sd->show_item;
638    dx = it->x + it->item->block->x;
639    dy = it->y + it->item->block->y;
640    dw = it->item->block->w;
641    dh = oh;
642 
643    if (dw < 1) return;
644    if (ow < 1 || oh < 1) return;
645 
646    switch (sd->scroll_to_type)
647      {
648       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
649         if (it->item->group_item) gith = it->item->group_item->item->h;
650         dy -= gith;
651         break;
652 
653       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
654         dy += ((it->item->h / 2) - (oh / 2));
655         break;
656 
657       case ELM_GENLIST_ITEM_SCROLLTO_BOTTOM:
658         dy += (it->item->h - oh);
659         break;
660 
661       case ELM_GENLIST_ITEM_SCROLLTO_IN:
662       default:
663         if ((sd->expanded_item) &&
664             ((sd->show_item->y + sd->show_item->item->block->y
665               + sd->show_item->item->h) -
666              (sd->expanded_item->y + sd->expanded_item->item->block->y) > oh))
667           {
668              it = sd->expanded_item;
669              if (it->item->group_item) gith = it->item->group_item->item->h;
670              dx = it->x + it->item->block->x;
671              dy = it->y + it->item->block->y - gith;
672              dw = it->item->block->w;
673           }
674         else
675           {
676              if ((it->item->group_item) &&
677                  (sd->pan_y > (it->y + it->item->block->y)))
678                gith = it->item->group_item->item->h;
679              dy -= gith;
680              dh = it->item->h;
681           }
682         break;
683      }
684    if (sd->bring_in)
685       elm_interface_scrollable_region_bring_in(sd->obj, dx, dy, dw, dh);
686    else
687       elm_interface_scrollable_content_region_show
688             (sd->obj, dx, dy, dw, dh);
689 
690    it->item->show_me = EINA_FALSE;
691    sd->show_item = NULL;
692    sd->auto_scroll_enabled = EINA_FALSE;
693    sd->check_scroll = EINA_FALSE;
694 }
695 
696 static void
_elm_genlist_item_unrealize(Elm_Gen_Item * it,Eina_Bool calc)697 _elm_genlist_item_unrealize(Elm_Gen_Item *it,
698                             Eina_Bool calc)
699 {
700    Evas *e;
701    if (!it->realized) return;
702    if (it->item->wsd->reorder_it == it)
703      {
704         WRN("reordering item should not be unrealized");
705         return;
706      }
707 
708    e = evas_object_evas_get(WIDGET(it));
709    evas_event_freeze(e);
710 
711    ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
712 
713    _view_clear(VIEW(it), &(it->texts), NULL);
714    ELM_SAFE_FREE(it->item_focus_chain, eina_list_free);
715 
716    elm_wdg_item_track_cancel(EO_OBJ(it));
717 
718    if (!calc)
719      {
720         efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_UNREALIZED, EO_OBJ(it));
721         if (it->base->func.unrealized) it->base->func.unrealized(EO_OBJ(it));
722      }
723 
724    _item_unrealize(it);
725 
726    evas_event_thaw(e);
727    evas_event_thaw_eval(e);
728 }
729 
730 static void
_item_block_unrealize(Item_Block * itb)731 _item_block_unrealize(Item_Block *itb)
732 {
733    Elm_Gen_Item *it;
734    const Eina_List *l;
735    Eina_Bool dragging = EINA_FALSE;
736    Evas *e;
737 
738    if (!itb->realized) return;
739    e = evas_object_evas_get((itb->sd)->obj);
740    evas_event_freeze(e);
741 
742    EINA_LIST_FOREACH(itb->items, l, it)
743      {
744         if (itb->must_recalc || !(it->item->type & ELM_GENLIST_ITEM_GROUP))
745           {
746              if (it->dragging)
747                {
748                   dragging = EINA_TRUE;
749                   it->want_unrealize = EINA_TRUE;
750                }
751              else if (it != itb->sd->pin_item)
752                _elm_genlist_item_unrealize(it, EINA_FALSE);
753           }
754      }
755    if (!dragging)
756      {
757         Eina_List *n;
758 
759         itb->realized = EINA_FALSE;
760         itb->want_unrealize = EINA_TRUE;
761 
762         efl_ui_focus_manager_calc_unregister(itb->sd->obj, itb->adapter);
763         efl_del(itb->adapter);
764         itb->adapter = NULL;
765 
766         EINA_LIST_FOREACH(itb->items, n, it)
767           {
768             efl_ui_focus_manager_calc_unregister(itb->sd->obj, EO_OBJ(it));
769           }
770      }
771    else
772      itb->want_unrealize = EINA_FALSE;
773    evas_event_thaw(e);
774    evas_event_thaw_eval(e);
775 }
776 
777 static Eina_Bool
_must_recalc_idler(void * data)778 _must_recalc_idler(void *data)
779 {
780    ELM_GENLIST_DATA_GET(data, sd);
781 
782    efl_canvas_group_change(sd->obj);
783    sd->must_recalc_idler = NULL;
784    return ECORE_CALLBACK_CANCEL;
785 }
786 
787 static void
_calc_job(void * data)788 _calc_job(void *data)
789 {
790    int in = 0;
791    Item_Block *itb, *chb = NULL;
792    Elm_Genlist_Data *sd = data;
793    Eina_Bool minw_change = EINA_FALSE;
794    Eina_Bool did_must_recalc = EINA_FALSE;
795    Evas_Coord minw = -1, minh = 0, y = 0, ow = 0, vw = 0;
796    Evas *e;
797 
798    sd->need_calc = EINA_FALSE;
799    evas_object_geometry_get(sd->pan_obj, NULL, NULL, &ow, &sd->h);
800    if (sd->mode == ELM_LIST_COMPRESS)
801       elm_interface_scrollable_content_viewport_geometry_get
802             (sd->obj, NULL, NULL, &vw, NULL);
803 
804    if (sd->w != ow) sd->w = ow;
805 
806    e = evas_object_evas_get(sd->obj);
807    evas_event_freeze(e);
808    EINA_INLIST_FOREACH(sd->blocks, itb)
809      {
810         Eina_Bool show_me = EINA_FALSE;
811 
812         itb->num = in;
813         show_me = itb->show_me;
814         itb->show_me = EINA_FALSE;
815         if (chb)
816           {
817              if (itb->realized) _item_block_unrealize(itb);
818           }
819         if ((itb->changed) || ((itb->must_recalc) && (!did_must_recalc)))
820           {
821              if (itb->must_recalc)
822                {
823                   Eina_List *l;
824                   Elm_Gen_Item *it;
825 
826                   EINA_LIST_FOREACH(itb->items, l, it)
827                     it->item->mincalcd = EINA_FALSE;
828                   itb->changed = EINA_TRUE;
829                   did_must_recalc = EINA_TRUE;
830                   if (itb->realized) _item_block_unrealize(itb);
831                   itb->must_recalc = EINA_FALSE;
832                }
833              show_me = _item_block_recalc(itb, in, EINA_FALSE);
834              chb = itb;
835           }
836         itb->y = y;
837         itb->x = 0;
838         minh += itb->minh;
839         if (minw < itb->minw)
840           {
841              minw = itb->minw;
842              if (minw != -1)
843                minw_change = EINA_TRUE;
844           }
845         if ((sd->mode == ELM_LIST_COMPRESS) && (minw > vw))
846           {
847              minw = vw;
848              minw_change = EINA_TRUE;
849           }
850         itb->w = minw;
851         itb->h = itb->minh;
852         y += itb->h;
853         in += itb->vis_count;
854         if ((show_me) && (sd->show_item) && (!sd->show_item->item->queued))
855           sd->check_scroll = EINA_TRUE;
856      }
857    if (minw_change)
858      {
859         EINA_INLIST_FOREACH(sd->blocks, itb)
860           {
861              itb->minw = minw;
862              itb->w = itb->minw;
863           }
864      }
865    if ((chb) && (EINA_INLIST_GET(chb)->next))
866      {
867         EINA_INLIST_FOREACH(EINA_INLIST_GET(chb)->next, itb)
868           {
869              if (itb->realized) _item_block_unrealize(itb);
870           }
871      }
872    sd->realminw = minw;
873    if (minw < sd->w) minw = sd->w;
874    if ((minw != sd->minw) || (minh != sd->minh))
875      {
876         sd->minw = minw;
877         sd->minh = minh;
878         efl_event_callback_legacy_call
879           (sd->pan_obj, ELM_PAN_EVENT_CHANGED, NULL);
880         elm_layout_sizing_eval(sd->obj);
881         if (sd->reorder_it)
882           {
883               Elm_Gen_Item *it;
884               it = sd->reorder_it;
885               it->item->w = minw;
886           }
887         if ((sd->anchor_item) && (sd->anchor_item->item->block)
888             && (!sd->auto_scroll_enabled))
889           {
890              Elm_Gen_Item *it;
891              Evas_Coord it_y;
892 
893              it = sd->anchor_item;
894              it_y = sd->anchor_y;
895              elm_interface_scrollable_content_pos_set
896                (sd->obj, sd->pan_x, it->item->block->y
897                + it->y + it_y, EINA_TRUE);
898              sd->anchor_item = it;
899              sd->anchor_y = it_y;
900           }
901      }
902    if (did_must_recalc)
903      {
904         if (!sd->must_recalc_idler)
905           sd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, sd->obj);
906      }
907    if (!sd->show_item) sd->check_scroll = EINA_FALSE;
908    if (sd->check_scroll)
909      {
910         if (EINA_INLIST_GET(sd->show_item) == sd->items->last)
911           sd->scroll_to_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
912 
913         if ((sd->show_item) && (sd->show_item->item->block))
914           _item_scroll(sd);
915      }
916 
917    evas_object_smart_changed(sd->pan_obj);
918    evas_event_thaw(e);
919    evas_event_thaw_eval(e);
920 }
921 
922 EOLIAN static void
_elm_genlist_efl_canvas_group_group_calculate(Eo * obj,Elm_Genlist_Data * sd)923 _elm_genlist_efl_canvas_group_group_calculate(Eo *obj, Elm_Genlist_Data *sd)
924 {
925    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
926    Evas_Coord vmw = 0, vmh = 0;
927 
928    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
929 
930    if (sd->on_sub_del) return;;
931 
932    evas_object_size_hint_combined_min_get(obj, &minw, NULL);
933    evas_object_size_hint_max_get(obj, &maxw, &maxh);
934 
935    edje_object_size_min_calc(wd->resize_obj, &vmw, &vmh);
936 
937    if (sd->mode == ELM_LIST_COMPRESS)
938      {
939         Evas_Coord vw = 0, vh = 0;
940 
941         elm_interface_scrollable_content_viewport_geometry_get
942               (obj, NULL, NULL, &vw, &vh);
943         if ((vw != 0) && (vw != sd->prev_viewport_w))
944           {
945              Item_Block *itb;
946 
947              sd->prev_viewport_w = vw;
948              /* Free all buckets for updaing changed width */
949              eina_hash_free_buckets(sd->size_caches);
950 
951              EINA_INLIST_FOREACH(sd->blocks, itb)
952                {
953                   itb->must_recalc = EINA_TRUE;
954                }
955              sd->need_calc = EINA_TRUE;
956           }
957         minw = vmw;
958         minh = vmh;
959      }
960    else
961      sd->need_calc = EINA_TRUE;
962    if (sd->need_calc)
963      _calc_job(sd);
964 
965    if (sd->scr_minw)
966      {
967         maxw = -1;
968         minw = vmw + sd->realminw;
969      }
970    else
971      {
972          minw = vmw;
973      }
974    if (sd->scr_minh)
975      {
976         maxh = -1;
977         minh = vmh + sd->minh;
978      }
979    else
980      {
981         minw = vmw;
982         minh = vmh;
983      }
984 
985    if ((maxw > 0) && (minw > maxw))
986      minw = maxw;
987    if ((maxh > 0) && (minh > maxh))
988      minh = maxh;
989 
990    evas_object_size_hint_min_set(obj, minw, minh);
991    evas_object_size_hint_max_set(obj, maxw, maxh);
992 }
993 
994 static void
_content_min_limit_cb(Evas_Object * obj,Eina_Bool w,Eina_Bool h)995 _content_min_limit_cb(Evas_Object *obj,
996                       Eina_Bool w,
997                       Eina_Bool h)
998 {
999    ELM_GENLIST_DATA_GET(obj, sd);
1000 
1001    if ((sd->mode == ELM_LIST_LIMIT) ||
1002        (sd->mode == ELM_LIST_EXPAND)) return;
1003    sd->scr_minw = !!w;
1004    sd->scr_minh = !!h;
1005 
1006    elm_layout_sizing_eval(obj);
1007 }
1008 
1009 static void
_item_contract_emit(Elm_Object_Item * eo_it)1010 _item_contract_emit(Elm_Object_Item *eo_it)
1011 {
1012    ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
1013    Elm_Object_Item *eo_it2;
1014    Eina_List *l;
1015 
1016    //XXX: for compat
1017    edje_object_signal_emit(VIEW(it), SIGNAL_CONTRACT_FLIP, "");
1018    edje_object_signal_emit(VIEW(it), SIGNAL_CONTRACT_FLIP, "elm");
1019    it->item->tree_effect_finished = EINA_FALSE;
1020 
1021    EINA_LIST_FOREACH(it->item->items, l, eo_it2)
1022      if (eo_it2) _item_contract_emit(eo_it2);
1023 }
1024 
1025 static int
_item_tree_effect_before(Elm_Gen_Item * it)1026 _item_tree_effect_before(Elm_Gen_Item *it)
1027 {
1028    Elm_Object_Item *eo_it2;
1029    Eina_List *l;
1030    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1031 
1032    EINA_LIST_FOREACH(it->item->items, l, eo_it2)
1033      {
1034         ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
1035         if (it2->parent && (it == it2->parent))
1036           {
1037              if (!it2->realized)
1038                it2->item->tree_effect_hide_me = EINA_TRUE;
1039              if (sd->move_effect_mode ==
1040                  ELM_GENLIST_TREE_EFFECT_EXPAND)
1041                {
1042                   //XXX: for compat
1043                   edje_object_signal_emit(VIEW(it2), SIGNAL_HIDE, "");
1044                   edje_object_signal_emit(VIEW(it2), SIGNAL_HIDE, "elm");
1045                }
1046              else if (sd->move_effect_mode ==
1047                       ELM_GENLIST_TREE_EFFECT_CONTRACT)
1048                _item_contract_emit(eo_it2);
1049           }
1050      }
1051    return ECORE_CALLBACK_CANCEL;
1052 }
1053 
1054 /* returns true if change occurred */
1055 static Eina_Bool
_item_position(Elm_Gen_Item * it,Evas_Object * view,Evas_Coord it_x,Evas_Coord it_y)1056 _item_position(Elm_Gen_Item *it,
1057                Evas_Object *view,
1058                Evas_Coord it_x,
1059                Evas_Coord it_y)
1060 {
1061    Eina_Position2D pos;
1062    if (!it) return EINA_FALSE;
1063    if (!view) return EINA_FALSE;
1064    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1065    Evas *e = evas_object_evas_get(sd->obj);
1066 
1067    evas_event_freeze(e);
1068    pos = efl_gfx_entity_position_get(view);
1069    efl_gfx_entity_geometry_set(view, EINA_RECT(it_x, it_y, it->item->w, it->item->h));
1070    evas_object_show(view);
1071    evas_event_thaw(e);
1072    evas_event_thaw_eval(e);
1073    return (pos.x != it_x) || (pos.y != it_y);
1074 }
1075 
1076 static void
_item_tree_effect(Elm_Genlist_Data * sd,int y)1077 _item_tree_effect(Elm_Genlist_Data *sd,
1078                   int y)
1079 {
1080    Elm_Gen_Item *expanded_next_it;
1081    Elm_Object_Item *eo_it;
1082 
1083    expanded_next_it = sd->expanded_next_item;
1084 
1085    if (sd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
1086      {
1087         eo_it = elm_genlist_item_prev_get(EO_OBJ(expanded_next_it));
1088         while (eo_it)
1089           {
1090              ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
1091              if (it->item->expanded_depth <=
1092                  expanded_next_it->item->expanded_depth) break;
1093              if (it->item->scrl_y &&
1094                  (it->item->scrl_y <= expanded_next_it->item->old_scrl_y + y)
1095                  && (it->item->expanded_depth >
1096                      expanded_next_it->item->expanded_depth))
1097                {
1098                   if (!it->item->tree_effect_finished)
1099                     {
1100                        //XXX: for compat
1101                        edje_object_signal_emit(VIEW(it), "flip_item", "");
1102                        edje_object_signal_emit(VIEW(it), SIGNAL_FLIP_ITEM,
1103                                                "elm");
1104                        _item_position
1105                          (it, VIEW(it), it->item->scrl_x, it->item->scrl_y);
1106                        it->item->tree_effect_finished = EINA_TRUE;
1107                     }
1108                }
1109              eo_it = elm_genlist_item_prev_get(eo_it);
1110           }
1111      }
1112    else if (sd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
1113      {
1114         eo_it = elm_genlist_item_prev_get(EO_OBJ(expanded_next_it));
1115         while (eo_it)
1116           {
1117              ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
1118              if ((it->item->scrl_y > expanded_next_it->item->old_scrl_y + y) &&
1119                  (it->item->expanded_depth >
1120                   expanded_next_it->item->expanded_depth))
1121                {
1122                   if (!it->item->tree_effect_finished)
1123                     {
1124                        //XXX: for compat
1125                        edje_object_signal_emit(VIEW(it), SIGNAL_HIDE, "");
1126                        edje_object_signal_emit(VIEW(it), SIGNAL_HIDE, "elm");
1127                        it->item->tree_effect_finished = EINA_TRUE;
1128                     }
1129                }
1130              else
1131                break;
1132              eo_it = elm_genlist_item_prev_get(eo_it);
1133           }
1134      }
1135 }
1136 
1137 static void
_item_sub_items_clear(Elm_Gen_Item * it)1138 _item_sub_items_clear(Elm_Gen_Item *it)
1139 {
1140    Eina_List *tl = NULL, *l;
1141    Elm_Object_Item *eo_it2;
1142 
1143    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
1144 
1145    EINA_LIST_FOREACH(it->item->items, l, eo_it2)
1146      tl = eina_list_append(tl, eo_it2);
1147    EINA_LIST_FREE(tl, eo_it2)
1148      efl_del(eo_it2);
1149 }
1150 
1151 static void
_item_auto_scroll(Elm_Genlist_Data * sd)1152 _item_auto_scroll(Elm_Genlist_Data *sd)
1153 {
1154    Elm_Object_Item *eo_tmp_item = NULL;
1155 
1156    if ((sd->expanded_item) && (sd->auto_scroll_enabled))
1157      {
1158         eo_tmp_item = eina_list_data_get
1159             (eina_list_last(sd->expanded_item->item->items));
1160         if (!eo_tmp_item) return;
1161         ELM_GENLIST_ITEM_DATA_GET(eo_tmp_item, tmp_item);
1162         sd->show_item = tmp_item;
1163         sd->bring_in = EINA_TRUE;
1164         sd->scroll_to_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
1165         if ((sd->show_item->item->queued) || (!sd->show_item->item->mincalcd))
1166           {
1167              sd->show_item->item->show_me = EINA_TRUE;
1168              sd->auto_scroll_enabled = EINA_FALSE;
1169           }
1170         else
1171           _item_scroll(sd);
1172      }
1173 }
1174 
1175 static void
_item_tree_effect_finish(Elm_Genlist_Data * sd)1176 _item_tree_effect_finish(Elm_Genlist_Data *sd)
1177 {
1178    Elm_Object_Item *eo_it = NULL;
1179    const Eina_List *l;
1180    Item_Block *itb;
1181    Elm_Gen_Item *it1;
1182    Evas_Coord y = 0;
1183 
1184    if (sd->tree_effect_animator)
1185      {
1186         if (sd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
1187           _item_sub_items_clear(sd->expanded_item);
1188 
1189         EINA_LIST_FOREACH(sd->expanded_item->item->items, l, eo_it)
1190           {
1191              ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
1192              it->item->tree_effect_finished = EINA_TRUE;
1193              it->item->old_scrl_y = it->item->scrl_y;
1194              if (it->item->wsd->move_effect_mode ==
1195                  ELM_GENLIST_TREE_EFFECT_EXPAND)
1196                {
1197                   //XXX: for compat
1198                   edje_object_signal_emit(VIEW(it), SIGNAL_SHOW, "");
1199                   edje_object_signal_emit(VIEW(it), SIGNAL_SHOW, "elm");
1200                }
1201           }
1202         if (sd->move_effect_mode ==
1203             ELM_GENLIST_TREE_EFFECT_EXPAND)
1204           {
1205              EINA_INLIST_FOREACH(sd->blocks, itb)
1206                {
1207                   EINA_LIST_FOREACH(itb->items, l, it1)
1208                    {
1209                        if (it1->item->scrl_y <= y)
1210                          {
1211                             it1->item->scrl_y = y + it1->item->h;
1212                             _elm_genlist_item_unrealize(it1, EINA_FALSE);
1213                          }
1214                        y = it1->item->scrl_y;
1215                    }
1216                }
1217           }
1218      }
1219 
1220    _item_auto_scroll(sd);
1221    evas_object_lower(sd->event_block_rect);
1222    evas_object_hide(sd->event_block_rect);
1223    sd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
1224    sd->move_items = eina_list_free(sd->move_items);
1225 
1226    efl_event_callback_legacy_call(sd->pan_obj, ELM_PAN_EVENT_CHANGED, NULL);
1227    efl_event_callback_legacy_call
1228          (sd->obj, ELM_GENLIST_EVENT_TREE_EFFECT_FINISHED, NULL);
1229    evas_object_smart_changed(sd->pan_obj);
1230 
1231    _elm_genlist_tree_effect_stop(sd);
1232 }
1233 
1234 static void
_item_restack(Elm_Gen_Item * it)1235 _item_restack(Elm_Gen_Item *it)
1236 {
1237    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1238 
1239    if (it->item->nostacking) return;
1240    if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
1241      {
1242         if (it->deco_all_view) evas_object_stack_below(it->deco_all_view, sd->stack[0]);
1243         else if (it->item->deco_it_view) evas_object_stack_below(it->item->deco_it_view, sd->stack[0]);
1244         else evas_object_stack_below(VIEW(it), sd->stack[0]);
1245      }
1246    else
1247      {
1248         if (it->deco_all_view) evas_object_stack_above(it->deco_all_view, sd->stack[0]);
1249         else if (it->item->deco_it_view) evas_object_stack_above(it->item->deco_it_view, sd->stack[0]);
1250         else evas_object_stack_above(VIEW(it), sd->stack[0]);
1251      }
1252 }
1253 
1254 static void
_elm_genlist_item_position_state_update(Elm_Gen_Item * it)1255 _elm_genlist_item_position_state_update(Elm_Gen_Item *it)
1256 {
1257    unsigned idx = it->item->order_num_in;
1258 
1259    if (!VIEW(it) && !it->deco_all_view) return;
1260    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1261 
1262    _item_restack(it);
1263 
1264    if (idx & 0x1)
1265      {
1266         edje_object_signal_emit(VIEW(it), SIGNAL_ODD, "elm");
1267         if (it->deco_all_view)
1268           edje_object_signal_emit(it->deco_all_view, SIGNAL_ODD, "elm");
1269      }
1270    else
1271      {
1272         edje_object_signal_emit(VIEW(it), SIGNAL_EVEN, "elm");
1273         if (it->deco_all_view)
1274           edje_object_signal_emit(it->deco_all_view, SIGNAL_EVEN, "elm");
1275      }
1276 
1277    if (sd->item_count == 1)
1278      {
1279         edje_object_signal_emit(VIEW(it), SIGNAL_LIST_SINGLE, "elm");
1280         if (it->deco_all_view)
1281           edje_object_signal_emit(it->deco_all_view, SIGNAL_LIST_SINGLE, "elm");
1282      }
1283    else if (idx == 0)
1284      {
1285         edje_object_signal_emit(VIEW(it), SIGNAL_LIST_FIRST, "elm");
1286         if (it->deco_all_view)
1287           edje_object_signal_emit(it->deco_all_view, SIGNAL_LIST_FIRST, "elm");
1288      }
1289    else if (idx == sd->item_count - 1)
1290      {
1291         edje_object_signal_emit(VIEW(it), SIGNAL_LIST_LAST, "elm");
1292         if (it->deco_all_view)
1293           edje_object_signal_emit(it->deco_all_view, SIGNAL_LIST_LAST, "elm");
1294      }
1295    else if (idx > 0)
1296      {
1297         edje_object_signal_emit(VIEW(it), SIGNAL_LIST_MIDDLE, "elm");
1298         if (it->deco_all_view)
1299           edje_object_signal_emit(it->deco_all_view, SIGNAL_LIST_MIDDLE, "elm");
1300      }
1301 
1302    if (it->parent)
1303      {
1304         unsigned first_idx = it->parent->item->order_num_in + 1;
1305         unsigned count = eina_list_count(it->parent->item->items);
1306 
1307         if (count == 1)
1308           {
1309              edje_object_signal_emit(VIEW(it), SIGNAL_GROUP_SINGLE, "elm");
1310              if (it->deco_all_view)
1311                edje_object_signal_emit(it->deco_all_view, SIGNAL_GROUP_SINGLE,
1312                                        "elm");
1313           }
1314         else if (idx == first_idx)
1315           {
1316              edje_object_signal_emit(VIEW(it), SIGNAL_GROUP_FIRST, "elm");
1317              if (it->deco_all_view)
1318                edje_object_signal_emit(it->deco_all_view, SIGNAL_GROUP_FIRST,
1319                                        "elm");
1320           }
1321         else if (EO_OBJ(it) == eina_list_data_get(eina_list_last(it->parent->item->items)))
1322           {
1323              edje_object_signal_emit(VIEW(it), SIGNAL_GROUP_LAST, "elm");
1324              if (it->deco_all_view)
1325                edje_object_signal_emit(it->deco_all_view, SIGNAL_GROUP_LAST,
1326                                        "elm");
1327           }
1328         else if (idx > first_idx)
1329           {
1330              edje_object_signal_emit(VIEW(it), SIGNAL_GROUP_MIDDLE, "elm");
1331              if (it->deco_all_view)
1332                edje_object_signal_emit(it->deco_all_view, SIGNAL_GROUP_MIDDLE,
1333                                        "elm");
1334           }
1335      }
1336 }
1337 
1338 static void
_item_order_update(Elm_Gen_Item * it,int index,Eina_Bool process)1339 _item_order_update(Elm_Gen_Item *it, int index, Eina_Bool process)
1340 {
1341    it->item->order_num_in = index;
1342    _elm_genlist_item_position_state_update(it);
1343 
1344    if (process) edje_object_message_signal_process(VIEW(it));
1345 }
1346 
1347 static void
_elm_genlist_item_state_update(Elm_Gen_Item * it)1348 _elm_genlist_item_state_update(Elm_Gen_Item *it)
1349 {
1350    if (it->selected)
1351      {
1352         edje_object_signal_emit(VIEW(it), SIGNAL_SELECTED, "elm");
1353         if (it->deco_all_view)
1354           edje_object_signal_emit
1355              (it->deco_all_view, SIGNAL_SELECTED, "elm");
1356      }
1357    if (elm_wdg_item_disabled_get(EO_OBJ(it)))
1358      {
1359         edje_object_signal_emit(VIEW(it), SIGNAL_DISABLED, "elm");
1360         if (it->deco_all_view)
1361           edje_object_signal_emit
1362              (it->deco_all_view, SIGNAL_DISABLED, "elm");
1363      }
1364    if (it->item->expanded)
1365      {
1366         edje_object_signal_emit(VIEW(it), SIGNAL_EXPANDED, "elm");
1367         if (it->deco_all_view)
1368           edje_object_signal_emit
1369              (it->deco_all_view, SIGNAL_EXPANDED, "elm");
1370      }
1371 }
1372 
1373 static void
_view_inflate(Evas_Object * view,Elm_Gen_Item * it,Eina_List ** sources,Eina_List ** contents,Eina_Bool calc)1374 _view_inflate(Evas_Object *view, Elm_Gen_Item *it, Eina_List **sources, Eina_List **contents, Eina_Bool calc)
1375 {
1376    if (!view) return;
1377    if (sources) _item_text_realize(it, view, sources, NULL);
1378    if (contents) _item_content_realize(it, view, contents, "contents", NULL, calc);
1379    _item_state_realize(it, view, NULL);
1380 }
1381 
1382 static void
_elm_genlist_item_index_update(Elm_Gen_Item * it)1383 _elm_genlist_item_index_update(Elm_Gen_Item *it)
1384 {
1385    if (it->position_update || it->item->block->position_update)
1386      {
1387         efl_event_callback_legacy_call
1388               (WIDGET(it), ELM_GENLIST_EVENT_INDEX_UPDATE, EO_OBJ(it));
1389         it->position_update = EINA_FALSE;
1390      }
1391 }
1392 
1393 static void
_decorate_all_item_position(Elm_Gen_Item * it,int itx,int ity)1394 _decorate_all_item_position(Elm_Gen_Item *it,
1395                             int itx,
1396                             int ity)
1397 {
1398    if ((!it) || (!it->item->wsd->decorate_all_mode)) return;
1399    efl_gfx_entity_geometry_set(it->deco_all_view, EINA_RECT(itx, ity, it->item->w, it->item->h));
1400 }
1401 
1402 static void
_decorate_all_item_realize(Elm_Gen_Item * it,Eina_Bool effect_on)1403 _decorate_all_item_realize(Elm_Gen_Item *it,
1404                            Eina_Bool effect_on)
1405 {
1406    char buf[1024];
1407    const char *stacking;
1408    const char *stacking_even;
1409 
1410    if (!it) return;
1411    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1412 
1413    if (it->item->decorate_all_item_realized) return;
1414 
1415    it->deco_all_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
1416    edje_object_scale_set(it->deco_all_view, efl_gfx_entity_scale_get(WIDGET(it)) *
1417                          elm_config_scale_get());
1418    evas_object_smart_member_add(it->deco_all_view, sd->pan_obj);
1419    elm_widget_sub_object_add(WIDGET(it), it->deco_all_view);
1420 
1421    if (it->item->type & ELM_GENLIST_ITEM_TREE)
1422      strncpy(buf, "tree", sizeof(buf));
1423    else strncpy(buf, "item", sizeof(buf));
1424    if (sd->mode == ELM_LIST_COMPRESS)
1425      strncat(buf, "_compress", sizeof(buf) - strlen(buf) - 1);
1426 
1427    strncat(buf, "/", sizeof(buf) - strlen(buf) - 1);
1428    strncat(buf, it->itc->decorate_all_item_style, sizeof(buf) - strlen(buf) - 1);
1429 
1430    elm_widget_theme_object_set(WIDGET(it), it->deco_all_view, "genlist", buf,
1431                                elm_widget_style_get(WIDGET(it)));
1432 
1433    stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
1434    if (!stacking_even) stacking_even = "above";
1435    it->item->stacking_even = !!strcmp("above", stacking_even);
1436 
1437    stacking = edje_object_data_get(VIEW(it), "stacking");
1438    if (!stacking) stacking = "yes";
1439    it->item->nostacking = !!strcmp("yes", stacking);
1440 
1441    edje_object_mirrored_set
1442      (it->deco_all_view, efl_ui_mirrored_get(WIDGET(it)));
1443 
1444    _elm_genlist_item_position_state_update(it);
1445    _elm_genlist_item_state_update(it);
1446 
1447    if (it->item->wsd->reorder_mode)
1448      {
1449         edje_object_signal_emit(it->deco_all_view, SIGNAL_REORDER_MODE_UNSET,
1450                                 "elm");
1451      }
1452 
1453    if (effect_on)
1454      edje_object_signal_emit
1455         (it->deco_all_view, SIGNAL_DECORATE_ENABLED_EFFECT, "elm");
1456    else
1457      edje_object_signal_emit
1458         (it->deco_all_view, SIGNAL_DECORATE_ENABLED, "elm");
1459 
1460    _item_mouse_callbacks_del(it, VIEW(it));
1461    _item_mouse_callbacks_add(it, it->deco_all_view);
1462 
1463    if (it->flipped)
1464      edje_object_signal_emit
1465        (it->deco_all_view, SIGNAL_FLIP_ENABLED, "elm");
1466    _view_inflate(it->deco_all_view, it, NULL, &(it->item->deco_all_contents), EINA_FALSE);
1467    edje_object_part_swallow
1468      (it->deco_all_view, "elm.swallow.decorate.content", VIEW(it));
1469 
1470    _decorate_all_item_position(it, it->item->scrl_x, it->item->scrl_y);
1471    evas_object_show(it->deco_all_view);
1472 
1473    if (it->selected)
1474      edje_object_signal_emit(it->deco_all_view, SIGNAL_SELECTED, "elm");
1475 
1476    it->item->decorate_all_item_realized = EINA_TRUE;
1477    it->want_unrealize = EINA_FALSE;
1478 }
1479 
1480 //-- tree expand/contract signal handle routine --//
1481 static void
_expand_toggle_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1482 _expand_toggle_signal_cb(void *data,
1483                          Evas_Object *obj EINA_UNUSED,
1484                          const char *emission EINA_UNUSED,
1485                          const char *source EINA_UNUSED)
1486 {
1487    Elm_Gen_Item *it = data;
1488 
1489    if (it->item->expanded)
1490      efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_CONTRACT_REQUEST, EO_OBJ(it));
1491    else
1492      efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_EXPAND_REQUEST, EO_OBJ(it));
1493 }
1494 
1495 static void
_expand_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1496 _expand_signal_cb(void *data,
1497                   Evas_Object *obj EINA_UNUSED,
1498                   const char *emission EINA_UNUSED,
1499                   const char *source EINA_UNUSED)
1500 {
1501    Elm_Gen_Item *it = data;
1502 
1503    if (!it->item->expanded)
1504      efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_EXPAND_REQUEST, EO_OBJ(it));
1505 }
1506 
1507 static void
_contract_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1508 _contract_signal_cb(void *data,
1509                     Evas_Object *obj EINA_UNUSED,
1510                     const char *emission EINA_UNUSED,
1511                     const char *source EINA_UNUSED)
1512 {
1513    Elm_Gen_Item *it = data;
1514 
1515    if (it->item->expanded)
1516      efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_CONTRACT_REQUEST, EO_OBJ(it));
1517 }
1518 
1519 //-- item cache handle routine --//
1520 // push item cache into caches
1521 static Eina_Bool
_item_cache_push(Elm_Genlist_Data * sd,Item_Cache * itc)1522 _item_cache_push(Elm_Genlist_Data *sd, Item_Cache *itc)
1523 {
1524    if (!itc || (sd->item_cache_max <= 0))
1525      return EINA_FALSE;
1526 
1527    sd->item_cache_count++;
1528    sd->item_cache =
1529      eina_inlist_prepend(sd->item_cache, EINA_INLIST_GET(itc));
1530 
1531    return EINA_TRUE;
1532 }
1533 
1534 // pop item cache from caches
1535 static Item_Cache *
_item_cache_pop(Elm_Genlist_Data * sd,Item_Cache * itc)1536 _item_cache_pop(Elm_Genlist_Data *sd, Item_Cache *itc)
1537 {
1538    if (!itc || (!sd->item_cache) ||
1539        (sd->item_cache_count <= 0))
1540      return NULL;
1541 
1542    sd->item_cache =
1543      eina_inlist_remove (sd->item_cache, EINA_INLIST_GET(itc));
1544    sd->item_cache_count--;
1545 
1546    return itc;
1547 }
1548 
1549 // free one item cache
1550 static void
_item_cache_free(Item_Cache * itc)1551 _item_cache_free(Item_Cache *itc)
1552 {
1553    Evas_Object *c;
1554 
1555    if (!itc) return;
1556 
1557    evas_object_del(itc->spacer);
1558    /* does not exist if cache item has just been reused */
1559    if (itc->base_view)
1560      {
1561         Evas_Object *view = itc->base_view;
1562         efl_wref_del(itc->base_view, &itc->base_view);
1563         efl_del(view);
1564         itc->base_view = NULL;
1565      }
1566    itc->item_class = NULL;
1567    EINA_LIST_FREE(itc->contents, c)
1568      {
1569         evas_object_del(c);
1570      }
1571    ELM_SAFE_FREE(itc, free);
1572 }
1573 
1574 // clean up item cache by removing overflowed caches
1575 static void
_item_cache_clean(Elm_Genlist_Data * sd)1576 _item_cache_clean(Elm_Genlist_Data *sd)
1577 {
1578    Evas *e;
1579 
1580    if (!sd->obj) return;
1581    e = evas_object_evas_get(sd->obj);
1582    evas_event_freeze(e);
1583 
1584    while ((sd->item_cache) && (sd->item_cache_count > sd->item_cache_max))
1585      {
1586         Item_Cache *itc =
1587            EINA_INLIST_CONTAINER_GET(sd->item_cache->last, Item_Cache);
1588         _item_cache_free(_item_cache_pop(sd, itc));
1589      }
1590    evas_event_thaw(e);
1591    evas_event_thaw_eval(e);
1592 }
1593 
1594 // empty all item caches
1595 static void
_item_cache_zero(Elm_Genlist_Data * sd)1596 _item_cache_zero(Elm_Genlist_Data *sd)
1597 {
1598    int pmax = sd->item_cache_max;
1599 
1600    sd->item_cache_max = 0;
1601    _item_cache_clean(sd);
1602    sd->item_cache_max = pmax;
1603 }
1604 
1605 // add an item to item cache
1606 static Eina_Bool
_item_cache_add(Elm_Gen_Item * it,Eina_List * contents)1607 _item_cache_add(Elm_Gen_Item *it, Eina_List *contents)
1608 {
1609    if (it->item->nocache_once || it->item->nocache) return EINA_FALSE;
1610 
1611    Item_Cache *itc = NULL;
1612    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1613    Evas_Object *obj = sd->obj;
1614    Evas_Object *win = efl_provider_find(obj, EFL_UI_WIN_CLASS);
1615    Evas *e = evas_object_evas_get(obj);
1616 
1617    evas_event_freeze(e);
1618 
1619    if (sd->item_cache_max > 0)
1620      itc = ELM_NEW(Item_Cache);
1621 
1622    if (!_item_cache_push(sd, itc))
1623      {
1624         if (itc) ELM_SAFE_FREE(itc, free);
1625 
1626         evas_event_thaw(e);
1627         evas_event_thaw_eval(e);
1628         return EINA_FALSE;
1629      }
1630    itc->spacer = it->spacer;
1631    efl_wref_add(VIEW(it), &itc->base_view);
1632    itc->item_class = it->itc;
1633    itc->contents = contents;
1634    if (it->item->type & ELM_GENLIST_ITEM_TREE)
1635      {
1636         itc->tree = 1;
1637         if (it->item->expanded)
1638           edje_object_signal_emit(itc->base_view, SIGNAL_CONTRACTED, "elm");
1639      }
1640 
1641    if (it->selected)
1642      edje_object_signal_emit(itc->base_view, SIGNAL_UNSELECTED, "elm");
1643    if (elm_wdg_item_disabled_get(EO_OBJ(it)))
1644      edje_object_signal_emit(itc->base_view, SIGNAL_ENABLED, "elm");
1645    if ((EO_OBJ(it) == sd->focused_item) &&
1646        (elm_win_focus_highlight_enabled_get(win) || _elm_config->win_auto_focus_enable))
1647      edje_object_signal_emit(itc->base_view, SIGNAL_UNFOCUSED, "elm");
1648 
1649    ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
1650    ELM_SAFE_FREE(it->item->swipe_timer, ecore_timer_del);
1651 
1652    // FIXME: other callbacks?
1653    edje_object_signal_callback_del_full
1654      (itc->base_view, "elm,action,expand,toggle", "elm",
1655      _expand_toggle_signal_cb, it);
1656    edje_object_signal_callback_del_full
1657      (itc->base_view, "elm,action,expand", "elm", _expand_signal_cb, it);
1658    edje_object_signal_callback_del_full
1659      (itc->base_view, "elm,action,contract", "elm", _contract_signal_cb, it);
1660    _item_mouse_callbacks_del(it, itc->base_view);
1661 
1662    edje_object_mirrored_set(itc->base_view,
1663                             efl_ui_mirrored_get(WIDGET(it)));
1664    edje_object_scale_set(itc->base_view,
1665                          efl_gfx_entity_scale_get(WIDGET(it))
1666                          * elm_config_scale_get());
1667 
1668    it->spacer = NULL;
1669    efl_wref_del(it->base->view, &it->base->view);
1670    VIEW(it) = NULL;
1671    evas_object_hide(itc->base_view);
1672 // lower eocalloverhead - no need to do this
1673 //   evas_object_move(itc->base_view, -9999, -9999);
1674 
1675    _item_cache_clean(sd);
1676 
1677    evas_event_thaw(e);
1678    evas_event_thaw_eval(e);
1679 
1680    return EINA_TRUE;
1681 }
1682 
1683 // find an item from item cache and remove it from the cache
1684 static Eina_Bool
_item_cache_find(Elm_Gen_Item * it)1685 _item_cache_find(Elm_Gen_Item *it)
1686 {
1687    if (it->item->nocache_once || it->item->nocache) return EINA_FALSE;
1688 
1689    Item_Cache *itc = NULL;
1690    Eina_Inlist *l;
1691    Eina_Bool tree = 0;
1692    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1693 
1694    if (it->item->type & ELM_GENLIST_ITEM_TREE) tree = 1;
1695    EINA_INLIST_FOREACH_SAFE(sd->item_cache, l, itc)
1696      {
1697         Evas_Object *obj;
1698 
1699         if ((itc->tree == tree) &&
1700             (((!it->itc) && (!itc->item_class)) ||
1701              (it->itc && itc->item_class &&
1702               (it->itc == itc->item_class))))
1703           {
1704              itc = _item_cache_pop(sd, itc);
1705              if (!itc) continue;
1706 
1707              it->spacer = itc->spacer;
1708              VIEW_SET(it, itc->base_view);
1709              itc->spacer = NULL;
1710              efl_wref_del(itc->base_view, &itc->base_view);
1711              itc->base_view = NULL;
1712              EINA_LIST_FREE(itc->contents, obj)
1713                {
1714                   if (elm_widget_is(obj))
1715                     elm_widget_tree_unfocusable_set(obj, it->item->unfocusable);
1716                   evas_object_show(obj);
1717                }
1718              itc->contents = NULL;
1719              _item_cache_free(itc);
1720              return EINA_TRUE;
1721           }
1722      }
1723    return EINA_FALSE;
1724 }
1725 
1726 static Eina_List *
_content_cache_add(Elm_Gen_Item * it,Eina_List ** cache)1727 _content_cache_add(Elm_Gen_Item *it, Eina_List **cache)
1728 {
1729    ELM_GENLIST_DATA_GET_FROM_ITEM(it, pd);
1730    Evas_Object *content = NULL;
1731    EINA_LIST_FREE(it->contents, content)
1732      {
1733         *cache = eina_list_append(*cache, content);
1734         eina_hash_del_by_key(pd->content_item_map, &content);
1735         if (elm_widget_is(content)) elm_widget_tree_unfocusable_set(content, EINA_TRUE);
1736         evas_object_hide(content);
1737      }
1738 
1739    return *cache;
1740 }
1741 
1742 static char *
_access_info_cb(void * data,Evas_Object * obj EINA_UNUSED)1743 _access_info_cb(void *data, Evas_Object *obj EINA_UNUSED)
1744 {
1745    char *ret;
1746    Eina_Strbuf *buf;
1747 
1748    Elm_Gen_Item *it = (Elm_Gen_Item *)data;
1749    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, NULL);
1750 
1751    buf = eina_strbuf_new();
1752 
1753    if (it->itc->func.text_get)
1754      {
1755         const Eina_List *l;
1756         const char *key;
1757 
1758         if (!(it->texts)) it->texts =
1759           elm_widget_stringlist_get(edje_object_data_get(VIEW(it), "texts"));
1760 
1761         EINA_LIST_FOREACH(it->texts, l, key)
1762           {
1763              char *s = it->itc->func.text_get
1764                 ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
1765 
1766              if (s)
1767                {
1768                   if (eina_strbuf_length_get(buf) > 0) eina_strbuf_append(buf, ", ");
1769                   eina_strbuf_append(buf, s);
1770                   free(s);
1771                }
1772           }
1773      }
1774 
1775    ret = eina_strbuf_string_steal(buf);
1776    eina_strbuf_free(buf);
1777    return ret;
1778 }
1779 
1780 static char *
_access_state_cb(void * data,Evas_Object * obj EINA_UNUSED)1781 _access_state_cb(void *data, Evas_Object *obj EINA_UNUSED)
1782 {
1783    Elm_Gen_Item *it = (Elm_Gen_Item *)data;
1784    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, NULL);
1785 
1786    if (it->base->disabled)
1787      return strdup(E_("State: Disabled"));
1788 
1789    return NULL;
1790 }
1791 
1792 static void
_access_on_highlight_cb(void * data)1793 _access_on_highlight_cb(void *data)
1794 {
1795    Evas_Coord x, y, w, h;
1796    Evas_Coord sx, sy, sw, sh;
1797    Elm_Gen_Item *it = (Elm_Gen_Item *)data;
1798    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
1799 
1800    evas_object_geometry_get(it->base->view, &x, &y, &w, &h);
1801    // XXX There would be a reason.
1802    if ((w == 0) && (h == 0)) return;
1803 
1804    evas_object_geometry_get(it->base->widget, &sx, &sy, &sw, &sh);
1805    if ((x < sx) || (y < sy) || ((x + w) > (sx + sw)) || ((y + h) > (sy + sh)))
1806      elm_genlist_item_bring_in(EO_OBJ(it),
1807                                ELM_GENLIST_ITEM_SCROLLTO_IN);
1808 }
1809 
1810 static void
_access_widget_item_register(Elm_Gen_Item * it)1811 _access_widget_item_register(Elm_Gen_Item *it)
1812 {
1813    Elm_Access_Info *ai;
1814 
1815    _elm_access_widget_item_register(it->base);
1816 
1817    ai = _elm_access_info_get(it->base->access_obj);
1818 
1819    _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
1820    _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
1821    _elm_access_on_highlight_hook_set(ai, _access_on_highlight_cb, it);
1822    _elm_access_activate_callback_set(ai, _access_activate_cb, EO_OBJ(it));
1823 }
1824 
1825 static void
_elm_genlist_item_focus_update(Elm_Gen_Item * it)1826 _elm_genlist_item_focus_update(Elm_Gen_Item *it)
1827 {
1828    const char *focus_raise;
1829    Evas_Object *obj = WIDGET(it);
1830    Evas_Object *win = efl_provider_find(obj, EFL_UI_WIN_CLASS);
1831    ELM_GENLIST_DATA_GET(obj, sd);
1832 
1833    if (elm_win_focus_highlight_enabled_get(win)
1834        || _elm_config->win_auto_focus_enable)
1835      edje_object_signal_emit(VIEW(it), SIGNAL_FOCUSED, "elm");
1836 
1837    focus_raise = edje_object_data_get(VIEW(it), "focusraise");
1838    if ((focus_raise) && (!strcmp(focus_raise, "on")))
1839      {
1840         Elm_Gen_Item *git;
1841         Eina_List *l;
1842 
1843         evas_object_raise(VIEW(it));
1844         EINA_LIST_FOREACH(sd->group_items, l, git)
1845           {
1846              if (git->realized) evas_object_raise(VIEW(git));
1847           }
1848      }
1849 }
1850 
1851 static void
_item_realize(Elm_Gen_Item * it,const int index,Eina_Bool calc)1852 _item_realize(Elm_Gen_Item *it, const int index, Eina_Bool calc)
1853 {
1854    const char *treesize;
1855    Item_Size *size = NULL;
1856    int tsize = 20;
1857    int in = index;
1858    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
1859 
1860    if (it->realized)
1861      {
1862         if (it->item->order_num_in != in)
1863           {
1864              _item_order_update(it, in, EINA_TRUE);
1865              _elm_genlist_item_index_update(it);
1866           }
1867         return;
1868      }
1869 
1870    if (sd->tree_effect_enabled ||
1871        (!_item_cache_find(it)))
1872      {
1873         VIEW_SET(it, _view_create(it, it->itc->item_style));
1874         if (it->item->nocache_once)
1875           it->item->nocache_once = EINA_FALSE;
1876      }
1877 
1878    /* access */
1879    if (_elm_config->access_mode) _access_widget_item_register(it);
1880 
1881    _item_order_update(it, in, EINA_FALSE);
1882 
1883    if (sd->reorder_mode)
1884      edje_object_signal_emit(VIEW(it), SIGNAL_REORDER_MODE_SET, "elm");
1885    else
1886      edje_object_signal_emit(VIEW(it), SIGNAL_REORDER_MODE_UNSET, "elm");
1887 
1888    treesize = edje_object_data_get(VIEW(it), "treesize");
1889    if (treesize) tsize = atoi(treesize);
1890 
1891    if (edje_object_part_exists(VIEW(it), "elm.swallow.pad"))
1892      {
1893         if (!it->spacer && treesize)
1894           {
1895              it->spacer =
1896                 evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
1897              evas_object_color_set(it->spacer, 0, 0, 0, 0);
1898              elm_widget_sub_object_add(WIDGET(it), it->spacer);
1899           }
1900 
1901         evas_object_size_hint_min_set
1902            (it->spacer, (it->item->expanded_depth * tsize) *
1903             elm_config_scale_get(), 1);
1904         edje_object_part_swallow(VIEW(it), "elm.swallow.pad", it->spacer);
1905      }
1906    else
1907      {
1908         ELM_SAFE_FREE(it->spacer, evas_object_del);
1909      }
1910 
1911    if (!calc)
1912      {
1913         edje_object_signal_callback_add
1914           (VIEW(it), "elm,action,expand,toggle", "elm",
1915           _expand_toggle_signal_cb, it);
1916         edje_object_signal_callback_add
1917           (VIEW(it), "elm,action,expand", "elm", _expand_signal_cb, it);
1918         edje_object_signal_callback_add
1919           (VIEW(it), "elm,action,contract", "elm", _contract_signal_cb, it);
1920         _item_mouse_callbacks_add(it, VIEW(it));
1921 
1922         if ((sd->decorate_all_mode) && (!it->deco_all_view) &&
1923             (it->item->type != ELM_GENLIST_ITEM_GROUP) &&
1924             (it->itc->decorate_all_item_style))
1925           _decorate_all_item_realize(it, EINA_FALSE);
1926 
1927         _elm_genlist_item_state_update(it);
1928         _elm_genlist_item_index_update(it);
1929 
1930         if (EO_OBJ(it) == sd->focused_item)
1931           {
1932              _elm_genlist_item_focus_update(it);
1933              _elm_widget_item_highlight_in_theme(WIDGET(it), EO_OBJ(it));
1934              _elm_widget_highlight_in_theme_update(WIDGET(it));
1935              _elm_widget_focus_highlight_start(WIDGET(it));
1936           }
1937      }
1938 
1939    size = eina_hash_find(sd->size_caches, &(it->itc));
1940    /* homogeneous genlist shortcut */
1941    if ((calc) && (sd->homogeneous) && (!it->item->mincalcd) && size)
1942      {
1943         it->item->w = it->item->minw = size->minw;
1944         it->item->h = it->item->minh = size->minh;
1945         size->expanded_depth = it->item->expanded_depth;
1946         it->item->mincalcd = EINA_TRUE;
1947      }
1948    else
1949      {
1950         if (eina_list_count(it->contents) != 0)
1951           ERR_ABORT("If you see this error, please notify us and we"
1952                     "will fix it");
1953 
1954         _view_inflate(VIEW(it), it, &it->texts, &it->contents, calc);
1955         if (it->has_contents != (!!it->contents))
1956           it->item->mincalcd = EINA_FALSE;
1957         it->has_contents = !!it->contents;
1958         if (it->flipped)
1959           {
1960              edje_object_signal_emit(VIEW(it), SIGNAL_FLIP_ENABLED, "elm");
1961              _item_content_realize(it, VIEW(it), &it->item->flip_contents,
1962                                    "flips", NULL, EINA_FALSE);
1963           }
1964 
1965         /* access: unregister item which have no text and content */
1966         if (_elm_config->access_mode && !it->texts && !it->contents)
1967           _elm_access_widget_item_unregister(it->base);
1968 
1969         if (!it->item->mincalcd)
1970           {
1971              if (sd->homogeneous && size)
1972                {
1973                   it->item->w = it->item->minw = size->minw;
1974                   it->item->h = it->item->minh = size->minh;
1975                   it->item->mincalcd = EINA_TRUE;
1976                   if (it->item->block->realized)
1977                     it->item->w = it->item->block->w;
1978                }
1979              else
1980                {
1981                   Evas_Coord mw = -1, mh = -1;
1982 
1983                   if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
1984                     elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1985                   if (sd->mode == ELM_LIST_COMPRESS)
1986                     mw = sd->prev_viewport_w;
1987                   // Process signal for proper size calc with text and content visible.
1988                   edje_object_message_signal_process(VIEW(it));
1989                   edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw, mh);
1990                   it->item->w = it->item->minw = mw;
1991                   it->item->h = it->item->minh = mh;
1992                   it->item->mincalcd = EINA_TRUE;
1993 
1994                   if (sd->homogeneous)
1995                     {
1996                        if (size)
1997                          eina_hash_del_by_key(sd->size_caches, &(it->itc));
1998 
1999                        size = ELM_NEW(Item_Size);
2000                        size->itc = it->itc;
2001                        size->expanded_depth = it->item->expanded_depth;
2002                        size->minw = mw;
2003                        size->minh = mh;
2004                        eina_hash_add(sd->size_caches, &(it->itc), size);
2005                     }
2006                }
2007           }
2008         if (!calc) evas_object_show(VIEW(it));
2009      }
2010 
2011    if (it->tooltip.content_cb)
2012      {
2013         elm_wdg_item_tooltip_content_cb_set(EO_OBJ(it), it->tooltip.content_cb, it->tooltip.data, NULL);
2014         elm_wdg_item_tooltip_style_set(EO_OBJ(it), it->tooltip.style);
2015         elm_wdg_item_tooltip_window_mode_set(EO_OBJ(it), it->tooltip.free_size);
2016      }
2017 
2018    if (it->mouse_cursor)
2019      elm_wdg_item_cursor_set(EO_OBJ(it), it->mouse_cursor);
2020 
2021    it->realized = EINA_TRUE;
2022    it->want_unrealize = EINA_FALSE;
2023 
2024    if (!calc)
2025      {
2026         if (it->item->tree_effect_hide_me)
2027           {
2028              if (sd->move_effect_mode
2029                  != ELM_GENLIST_TREE_EFFECT_NONE)
2030                {
2031                   //XXX: for compat
2032                   edje_object_signal_emit(VIEW(it), SIGNAL_HIDE, "");
2033                   edje_object_signal_emit(VIEW(it), SIGNAL_HIDE, "elm");
2034                }
2035              it->item->tree_effect_hide_me = EINA_FALSE;
2036           }
2037 
2038         if (it->item->type == ELM_GENLIST_ITEM_NONE)
2039           {
2040              Evas_Object* eobj;
2041              Eina_List* l;
2042              EINA_LIST_FOREACH(it->contents, l, eobj)
2043                 if (elm_widget_is(eobj) && elm_object_focus_allow_get(eobj))
2044                   it->item_focus_chain = eina_list_append
2045                       (it->item_focus_chain, eobj);
2046 
2047           }
2048 
2049         if (it->item->type == ELM_GENLIST_ITEM_TREE)
2050           {
2051              Evas_Object* t_eobj;
2052              Eina_List* tl;
2053              EINA_LIST_FOREACH(it->contents, tl, t_eobj)
2054                 if (elm_widget_is(t_eobj) && elm_object_focus_allow_get(t_eobj))
2055                   it->item_focus_chain = eina_list_append
2056                       (it->item_focus_chain, t_eobj);
2057 
2058           }
2059 
2060         efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_REALIZED, EO_OBJ(it));
2061         if (it->base->func.realized) it->base->func.realized(EO_OBJ(it));
2062      }
2063 
2064    //Send a signal so that an item changes its style according to its expand depth
2065    if (it->item->expanded_depth > 0)
2066      {
2067         char buf[126];
2068         snprintf(buf, sizeof(buf), "elm,state,expanded_depth,%d",
2069                  it->item->expanded_depth);
2070         edje_object_signal_emit(VIEW(it), buf, "elm");
2071      }
2072 
2073    if ((!calc) && (sd->decorate_all_mode) &&
2074        (it->item->type != ELM_GENLIST_ITEM_GROUP))
2075      {
2076         if (it->itc->decorate_all_item_style)
2077           {
2078              if (!it->deco_all_view)
2079                _decorate_all_item_realize(it, EINA_FALSE);
2080              edje_object_message_signal_process(it->deco_all_view);
2081           }
2082      }
2083 
2084    if (it->decorate_it_set) _decorate_item_set(it);
2085 
2086    edje_object_message_signal_process(VIEW(it));
2087 
2088    if (sd->focus_on_realization == it)
2089      {
2090         _elm_widget_item_highlight_in_theme(WIDGET(it), EO_OBJ(it));
2091         _elm_widget_highlight_in_theme_update(WIDGET(it));
2092         _elm_widget_focus_highlight_start(WIDGET(it));
2093         efl_ui_focus_manager_focus_set(WIDGET(it), EO_OBJ(it));
2094         sd->focus_on_realization = NULL;
2095      }
2096 }
2097 
2098 static void
_tree_effect_animator_cb(void * data,const Efl_Event * event EINA_UNUSED)2099 _tree_effect_animator_cb(void *data, const Efl_Event *event EINA_UNUSED)
2100 {
2101    int in = 0;
2102    const Eina_List *l;
2103    int y = 0, dy = 0, dh = 0;
2104    double effect_duration = 0.3, t;
2105    ELM_GENLIST_DATA_GET(data, sd);
2106    Eina_Bool end = EINA_FALSE, vis = EINA_TRUE;
2107    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2108    Elm_Gen_Item *it = NULL, *it2, *expanded_next_it;
2109    Elm_Object_Item *eo_it = NULL, *eo_it2;
2110 
2111    t = ((0.0 > (t = ecore_time_get() - sd->start_time)) ? 0.0 : t);
2112    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
2113    evas_output_viewport_get
2114      (evas_object_evas_get(sd->pan_obj), &cvx, &cvy, &cvw, &cvh);
2115    if (t > effect_duration) end = EINA_TRUE;
2116 
2117    // Below while statement is needed, when the genlist is resized.
2118    it2 = sd->expanded_item;
2119    eo_it2 = EO_OBJ(it2);
2120    while (eo_it2 && vis)
2121      {
2122         it2 = efl_data_scope_get(eo_it2, ELM_GENLIST_ITEM_CLASS);
2123         evas_object_move(VIEW(it2), it2->item->scrl_x, it2->item->scrl_y);
2124         vis = (ELM_RECTS_INTERSECT(it2->item->scrl_x, it2->item->scrl_y,
2125                                    it2->item->w, it2->item->h, cvx, cvy, cvw,
2126                                    cvh));
2127         eo_it2 = elm_genlist_item_prev_get(eo_it2);
2128      }
2129 
2130    if (sd->expanded_next_item)
2131      {
2132         expanded_next_it = sd->expanded_next_item;
2133 
2134         /* move items */
2135         EINA_LIST_FOREACH(sd->move_items, l, it)
2136           {
2137              if (sd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
2138                {
2139                   expanded_next_it->item->old_scrl_y =
2140                     sd->expanded_item->item->old_scrl_y
2141                     + sd->expanded_item->item->h;
2142                   if (expanded_next_it->item->scrl_y <=
2143                       expanded_next_it->item->old_scrl_y) /* did not
2144                                                            * calculate
2145                                                            * next item
2146                                                            * position */
2147                     expanded_next_it->item->scrl_y = cvy + cvh;
2148 
2149                   dy = ((expanded_next_it->item->scrl_y >= (cvy + cvh)) ?
2150                         cvy + cvh : expanded_next_it->item->scrl_y) -
2151                     expanded_next_it->item->old_scrl_y;
2152                }
2153              else if (sd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
2154                {
2155                   if (expanded_next_it->item->scrl_y >
2156                       expanded_next_it->item->old_scrl_y) /* did not
2157                                                            * calculate
2158                                                            * next item
2159                                                            * position */
2160                     expanded_next_it->item->old_scrl_y = cvy + cvh;
2161 
2162                   if (expanded_next_it->item->old_scrl_y > (cvy + cvh))
2163                     {
2164                        dy = (sd->expanded_item->item->scrl_y +
2165                              sd->expanded_item->item->h) - cvy + cvh;
2166                        expanded_next_it->item->old_scrl_y = cvy + cvh;
2167                     }
2168                   else
2169                     {
2170                        dy = (sd->expanded_item->item->scrl_y +
2171                              sd->expanded_item->item->h) -
2172                          expanded_next_it->item->old_scrl_y;
2173                     }
2174                }
2175 
2176              if (t <= effect_duration)
2177                {
2178                   y = ((1 - (1 - (t / effect_duration)) *
2179                         (1 - (t / effect_duration))) * dy);
2180                }
2181              else
2182                {
2183                   end = EINA_TRUE;
2184                   y = dy;
2185                }
2186 
2187              if (!it->realized && !it->item->queued)
2188                _item_realize(it, in, 0);
2189              if (!it->hide) in++;
2190 
2191              if (it != expanded_next_it)
2192                {
2193                   it->item->old_scrl_y =
2194                     expanded_next_it->item->old_scrl_y +
2195                     expanded_next_it->item->h + dh;
2196 
2197                   dh += it->item->h;
2198                }
2199 
2200              if ((it->item->old_scrl_y + y) < (cvy + cvh))
2201                _item_position(it, VIEW(it), it->item->scrl_x,
2202                               it->item->old_scrl_y + y);
2203           }
2204         /* tree effect */
2205         _item_tree_effect(sd, y);
2206      }
2207    else
2208      {
2209         int expanded_item_num = 0;
2210         int num = 0;
2211 
2212         if (sd->expanded_item)
2213           eo_it = elm_genlist_item_next_get(EO_OBJ(sd->expanded_item));
2214 
2215         eo_it2 = eo_it;
2216         while (eo_it2)
2217           {
2218              expanded_item_num++;
2219              eo_it2 = elm_genlist_item_next_get(eo_it2);
2220           }
2221 
2222         while (eo_it)
2223           {
2224              it = efl_data_scope_get(eo_it, ELM_GENLIST_ITEM_CLASS);
2225              num++;
2226              if (sd->expanded_item->item->expanded_depth >=
2227                  it->item->expanded_depth) break;
2228              if (sd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
2229                {
2230                   if (!it->item->tree_effect_finished)
2231                     {
2232                        if (t >= (((num - 1) * effect_duration) /
2233                                  expanded_item_num))
2234                          {
2235                             //XXX: for compat
2236                             edje_object_signal_emit(VIEW(it), "flip_item", "");
2237                             edje_object_signal_emit(VIEW(it), SIGNAL_FLIP_ITEM,
2238                                                     "elm");
2239                             _item_position(it, VIEW(it), it->item->scrl_x,
2240                                            it->item->scrl_y);
2241                             it->item->tree_effect_finished = EINA_TRUE;
2242                          }
2243                     }
2244                }
2245              eo_it = elm_genlist_item_next_get(eo_it);
2246           }
2247      }
2248 
2249    if (end)
2250      {
2251         _item_tree_effect_finish(sd);
2252         _elm_genlist_tree_effect_stop(sd);
2253      }
2254 }
2255 
2256 static void
_group_items_recalc(void * data)2257 _group_items_recalc(void *data)
2258 {
2259    Eina_List *l;
2260    Elm_Gen_Item *git;
2261    Elm_Genlist_Data *sd = data;
2262    Evas_Coord vy;
2263    Evas *e = evas_object_evas_get(sd->obj);
2264 
2265    evas_event_freeze(e);
2266    EINA_LIST_FOREACH(sd->group_items, l, git)
2267      {
2268         if (git->item->want_realize)
2269           {
2270              if (!git->realized) _item_realize(git, git->item->order_num_in, EINA_FALSE);
2271              if (sd->pin_item && git == sd->pin_item->item->group_item &&
2272                  sd->pin_item->item->scrl_y <= (git->item->scrl_y + git->item->h))
2273                {
2274                   elm_interface_scrollable_content_viewport_geometry_get
2275                     (sd->obj, NULL, &vy, NULL, NULL);
2276                   if ((git->item->scrl_y + git->item->h) > vy)
2277                     {
2278                        sd->pin_item->item->scrl_y = git->item->scrl_y + git->item->h;
2279                        evas_object_move(VIEW(sd->pin_item),
2280                                         sd->pin_item->item->scrl_x, sd->pin_item->item->scrl_y);
2281                     }
2282                }
2283              else if (sd->pin_item && sd->pin_item_top && git != sd->pin_item->item->group_item &&
2284                       (git->item->scrl_y < (sd->pin_item->item->scrl_y + sd->pin_item->item->h)))
2285                git->item->scrl_y = sd->pin_item->item->scrl_y + sd->pin_item->item->h;
2286 
2287              efl_gfx_entity_geometry_set(VIEW(git), EINA_RECT(git->item->scrl_x, git->item->scrl_y, sd->minw, git->item->h));
2288              evas_object_stack_above(VIEW(git), sd->stack[1]);
2289              evas_object_show(VIEW(git));
2290           }
2291         else if (!git->item->want_realize && git->realized)
2292           {
2293              if (!git->dragging)
2294                _elm_genlist_item_unrealize(git, EINA_FALSE);
2295           }
2296      }
2297    evas_event_thaw(e);
2298    evas_event_thaw_eval(e);
2299 }
2300 
2301 static Eina_Bool
_reorder_move_animator_cb(void * data)2302 _reorder_move_animator_cb(void *data)
2303 {
2304    double t;
2305    Elm_Gen_Item *it = data;
2306    Eina_Bool down = EINA_FALSE;
2307    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
2308    int y, dy = it->item->h / 10 * elm_config_scale_get(), diff;
2309 
2310    t = ((0.0 > (t = ecore_loop_time_get()
2311                   - sd->start_time)) ? 0.0 : t);
2312 
2313    if (t <= REORDER_EFFECT_TIME)
2314      y = (1 * sin((t / REORDER_EFFECT_TIME) * (M_PI / 2)) * dy);
2315    else y = dy;
2316 
2317    diff = abs(it->item->old_scrl_y - it->item->scrl_y);
2318    if (diff < dy) y = diff;
2319    else if (diff > it->item->h) y = diff / 2;
2320 
2321    if (it->item->old_scrl_y < it->item->scrl_y)
2322      {
2323         it->item->old_scrl_y += y;
2324         down = EINA_TRUE;
2325      }
2326    else if (it->item->old_scrl_y > it->item->scrl_y)
2327      {
2328         it->item->old_scrl_y -= y;
2329         down = EINA_FALSE;
2330      }
2331 
2332    if (it->deco_all_view)
2333      _item_position
2334        (it, it->deco_all_view, it->item->scrl_x, it->item->old_scrl_y);
2335    else
2336      _item_position(it, VIEW(it), it->item->scrl_x, it->item->old_scrl_y);
2337    _group_items_recalc(sd);
2338 
2339    if ((sd->reorder_pan_move) ||
2340        (down && it->item->old_scrl_y >= it->item->scrl_y) ||
2341        (!down && it->item->old_scrl_y <= it->item->scrl_y))
2342      {
2343         it->item->old_scrl_y = it->item->scrl_y;
2344         it->item->move_effect_enabled = EINA_FALSE;
2345         sd->reorder_move_animator = NULL;
2346         return ECORE_CALLBACK_CANCEL;
2347      }
2348 
2349    return ECORE_CALLBACK_RENEW;
2350 }
2351 
2352 static int
_reorder_item_space_get(Elm_Gen_Item * it)2353 _reorder_item_space_get(Elm_Gen_Item *it)
2354 {
2355    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
2356    Elm_Gen_Item *reorder_it = sd->reorder_it;
2357    Evas_Coord rox, roy, row, roh, oy, oh;
2358    Eina_Bool top = EINA_FALSE;
2359 
2360    if (!reorder_it) return 0;
2361 
2362    evas_object_geometry_get(sd->pan_obj, NULL, &oy, NULL, &oh);
2363    evas_object_geometry_get
2364      (sd->VIEW(reorder_it), &rox, &roy, &row, &roh);
2365 
2366    if ((sd->reorder_start_y < it->item->block->y) &&
2367        (roy - oy + (roh / 2) >= it->item->block->y - sd->pan_y))
2368      {
2369         it->item->block->reorder_offset =
2370           sd->reorder_it->item->h * -1;
2371         if (it->item->block->count == 1)
2372           sd->reorder_rel = it;
2373      }
2374    else if ((sd->reorder_start_y >= it->item->block->y) &&
2375             (roy - oy + (roh / 2) <= it->item->block->y - sd->pan_y))
2376      {
2377         it->item->block->reorder_offset = sd->reorder_it->item->h;
2378      }
2379    else
2380      it->item->block->reorder_offset = 0;
2381 
2382    it->item->scrl_y += it->item->block->reorder_offset;
2383 
2384    top = (ELM_RECTS_INTERSECT
2385             (it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2386             rox, roy + (roh / 2), row, 1));
2387    if (top)
2388      {
2389         sd->reorder_rel = it;
2390         it->item->scrl_y += sd->reorder_it->item->h;
2391         return sd->reorder_it->item->h;
2392      }
2393    else
2394      return 0;
2395 }
2396 
2397 static void
_pin_item_recalc(Elm_Gen_Item * it)2398 _pin_item_recalc(Elm_Gen_Item *it)
2399 {
2400    Evas_Coord vx, vy, vw, vh;
2401    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
2402 
2403    sd->pin_item_top = EINA_FALSE;
2404    elm_interface_scrollable_content_viewport_geometry_get
2405      (sd->obj, &vx, &vy, &vw, &vh);
2406    if (it->item->scrl_x < vx)
2407      it->item->scrl_x = vx;
2408    else if (it->item->scrl_x + it->item->w > vx + vw)
2409      it->item->scrl_x = vx + vw - it->item->w;
2410 
2411    if (it->item->scrl_y < vy)
2412    {
2413       sd->pin_item_top = EINA_TRUE;
2414       it->item->scrl_y = vy;
2415    }
2416    else if (it->item->scrl_y + it->item->h > vy + vh)
2417      it->item->scrl_y = vy + vh - it->item->h;
2418 
2419    efl_gfx_entity_geometry_set(VIEW(it), EINA_RECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h));
2420    evas_object_show(VIEW(it));
2421 }
2422 
2423 static void
_item_block_position(Item_Block * itb,const int blk_idx)2424 _item_block_position(Item_Block *itb, const int blk_idx)
2425 {
2426    Elm_Gen_Item *it;
2427    Elm_Gen_Item *git;
2428    const Eina_List *l;
2429    Eina_Bool vis = EINA_FALSE;
2430    Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2431    Elm_Genlist_Data *sd = NULL;
2432    int vis_count = 0;
2433    Evas *e = evas_object_evas_get((itb->sd)->obj);
2434 
2435    evas_event_freeze(e);
2436    evas_object_geometry_get(itb->sd->pan_obj, &ox, &oy, &ow, &oh);
2437    evas_output_viewport_get(e, &cvx, &cvy, &cvw, &cvh);
2438 
2439    EINA_LIST_FOREACH(itb->items, l, it)
2440      {
2441         sd = it->item->wsd;
2442         if (sd->reorder_it == it) continue;
2443 
2444         if (it->itc->func.filter_get)
2445           _item_filtered_get(it, sd);
2446         if (it->hide)
2447           {
2448              if (it->realized) evas_object_hide(VIEW(it));
2449              continue;
2450           }
2451         it->x = 0;
2452         it->y = y;
2453         it->item->w = itb->w;
2454         it->item->scrl_x = itb->x + it->x - sd->pan_x + ox;
2455         it->item->scrl_y = itb->y + it->y - sd->pan_y + oy;
2456 
2457         vis = (ELM_RECTS_INTERSECT
2458                  (it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2459                  cvx, cvy, cvw, cvh));
2460         if (!(it->item->type & ELM_GENLIST_ITEM_GROUP))
2461           {
2462              if ((itb->realized) && (!it->realized))
2463                {
2464                   if (vis) _item_realize(it, blk_idx + vis_count, EINA_FALSE);
2465                }
2466              if ((blk_idx + vis_count) != it->item->order_num_in)
2467                {
2468                   _item_order_update(it, blk_idx + vis_count, EINA_TRUE);
2469                }
2470              if (it->realized)
2471                {
2472                   if (vis || it->dragging)
2473                     {
2474                        if (sd->reorder_mode)
2475                          y += _reorder_item_space_get(it);
2476                        git = it->item->group_item;
2477                        if (git)
2478                          {
2479                             if (git->item->scrl_y < oy)
2480                               git->item->scrl_y = oy;
2481                             if ((git->item->scrl_y + git->item->h) >
2482                                 (it->item->scrl_y + it->item->h))
2483                               git->item->scrl_y = (it->item->scrl_y +
2484                                                    it->item->h) - git->item->h;
2485                             git->item->scrl_x = it->item->scrl_x;
2486                             git->item->want_realize = EINA_TRUE;
2487                          }
2488                        if ((sd->reorder_it) &&
2489                            (it->item->old_scrl_y != it->item->scrl_y))
2490                          {
2491                             if (!it->item->move_effect_enabled)
2492                               {
2493                                  it->item->move_effect_enabled = EINA_TRUE;
2494                                  sd->reorder_move_animator =
2495                                    ecore_evas_animator_add(e,
2496                                      _reorder_move_animator_cb, it);
2497                               }
2498                          }
2499                        if (!it->item->move_effect_enabled)
2500                          {
2501                             if ((sd->decorate_all_mode) &&
2502                                 (it->itc->decorate_all_item_style))
2503                               _decorate_all_item_position
2504                                 (it, it->item->scrl_x, it->item->scrl_y);
2505                             else
2506                               {
2507                                  if (!sd->tree_effect_enabled ||
2508                                      (sd->move_effect_mode ==
2509                                       ELM_GENLIST_TREE_EFFECT_NONE) ||
2510                                      ((sd->move_effect_mode !=
2511                                        ELM_GENLIST_TREE_EFFECT_NONE) &&
2512                                       (it->item->old_scrl_y ==
2513                                        it->item->scrl_y)))
2514                                    {
2515                                       if (it->item->deco_it_view)
2516                                         _item_position
2517                                           (it, it->item->deco_it_view,
2518                                           it->item->scrl_x,
2519                                           it->item->scrl_y);
2520                                       else
2521                                         _item_position
2522                                           (it, VIEW(it), it->item->scrl_x,
2523                                           it->item->scrl_y);
2524                                    }
2525                               }
2526                             it->item->old_scrl_y = it->item->scrl_y;
2527                          }
2528                     }
2529                   else
2530                     {
2531                        if (!sd->tree_effect_animator && (it != sd->pin_item))
2532                          _elm_genlist_item_unrealize(it, EINA_FALSE);
2533                     }
2534                }
2535           }
2536         else
2537           {
2538              if (vis) it->item->want_realize = EINA_TRUE;
2539           }
2540         y += it->item->h;
2541         vis_count++;
2542 
2543         if (it == sd->pin_item)
2544           _pin_item_recalc(it);
2545      }
2546 
2547    evas_event_thaw(e);
2548    evas_event_thaw_eval(e);
2549 }
2550 
2551 static inline void
_flush_block_order(Elm_Genlist_Data * sd)2552 _flush_block_order(Elm_Genlist_Data *sd)
2553 {
2554    Item_Block *itb;
2555    Eina_List *blocks = NULL;
2556 
2557    EINA_INLIST_FOREACH(sd->blocks, itb)
2558      {
2559         if (itb->adapter)
2560           blocks = eina_list_append(blocks, itb->adapter);
2561      }
2562 
2563    efl_ui_focus_manager_calc_update_order(sd->obj, sd->obj, blocks);
2564 }
2565 
2566 static void
_item_block_realize(Item_Block * itb)2567 _item_block_realize(Item_Block *itb)
2568 {
2569    Elm_Gen_Item *it;
2570    Eina_List *n;
2571 
2572    if (itb->realized) return;
2573 
2574    itb->realized = EINA_TRUE;
2575    itb->want_unrealize = EINA_FALSE;
2576 
2577    if (!itb->adapter)
2578      {
2579         itb->adapter = efl_add(EFL_UI_FOCUS_COMPOSITION_ADAPTER_CLASS, itb->sd->obj);
2580         efl_ui_focus_composition_adapter_focus_manager_parent_set(itb->adapter, itb->sd->obj);
2581         efl_ui_focus_composition_adapter_focus_manager_object_set(itb->adapter, itb->sd->obj);
2582         efl_ui_focus_manager_calc_register_logical(itb->sd->obj, itb->adapter, itb->sd->obj, NULL);
2583         _flush_block_order(itb->sd);
2584      }
2585 
2586    EINA_LIST_FOREACH(itb->items, n, it)
2587      {
2588         efl_ui_focus_manager_calc_register_logical(itb->sd->obj, EO_OBJ(it), itb->adapter, NULL);
2589      }
2590 }
2591 
2592 static Eina_Bool
_elm_genlist_tree_effect_setup(Elm_Genlist_Data * sd)2593 _elm_genlist_tree_effect_setup(Elm_Genlist_Data *sd)
2594 {
2595    if (!sd->tree_effect_animator)
2596      {
2597         _item_tree_effect_before(sd->expanded_item);
2598         evas_object_raise(sd->event_block_rect);
2599         evas_object_stack_below(sd->event_block_rect, sd->stack[1]);
2600         evas_object_show(sd->event_block_rect);
2601         sd->start_time = ecore_time_get();
2602         efl_event_callback_add(sd->obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _tree_effect_animator_cb, sd->obj);
2603         sd->tree_effect_animator = 1;
2604         return EINA_TRUE;
2605      }
2606    return EINA_FALSE;
2607 }
2608 
2609 static void
_elm_genlist_tree_effect_stop(Elm_Genlist_Data * sd)2610 _elm_genlist_tree_effect_stop(Elm_Genlist_Data *sd)
2611 {
2612    if (sd->tree_effect_animator)
2613      {
2614         sd->tree_effect_animator = 0;
2615         efl_event_callback_del(sd->obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _tree_effect_animator_cb, sd->obj);
2616      }
2617 }
2618 
2619 EOLIAN static void
_elm_genlist_pan_efl_canvas_group_group_calculate(Eo * obj,Elm_Genlist_Pan_Data * psd)2620 _elm_genlist_pan_efl_canvas_group_group_calculate(Eo *obj, Elm_Genlist_Pan_Data *psd)
2621 {
2622    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2623    Evas_Coord vx = 0, vy = 0, vw = 0, vh = 0;
2624    Elm_Gen_Item *git;
2625    Item_Block *itb;
2626    Eina_List *l;
2627    int in = 0;
2628    Evas *e = evas_object_evas_get(obj);;
2629 
2630    Elm_Genlist_Data *sd = psd->wsd;
2631 
2632    efl_canvas_group_need_recalculate_set(obj, EINA_FALSE);
2633    evas_event_freeze(e);
2634 
2635    if (sd->pan_changed)
2636      {
2637         _calc_job(sd);
2638         sd->pan_changed = EINA_FALSE;
2639      }
2640 
2641    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
2642    evas_output_viewport_get(e, &cvx, &cvy, &cvw, &cvh);
2643 
2644    if (sd->tree_effect_enabled &&
2645        (sd->move_effect_mode != ELM_GENLIST_TREE_EFFECT_NONE))
2646      {
2647         _elm_genlist_tree_effect_setup(sd);
2648      }
2649 
2650    EINA_INLIST_FOREACH(sd->blocks, itb)
2651      {
2652         itb->w = sd->minw;
2653         if (ELM_RECTS_INTERSECT(itb->x - sd->pan_x + ox,
2654                                 itb->y - sd->pan_y + oy,
2655                                 itb->w, itb->h,
2656                                 cvx, cvy, cvw, cvh))
2657           {
2658              if ((!itb->realized) || (itb->changed))
2659                _item_block_realize(itb);
2660              _item_block_position(itb, in);
2661           }
2662         else
2663           {
2664              if (itb->realized) _item_block_unrealize(itb);
2665              if (sd->pin_item && itb == sd->pin_item->item->block)
2666                {
2667                   if (!sd->pin_item->realized)
2668                     _item_realize(sd->pin_item, sd->pin_item->item->order_num_in, EINA_FALSE);
2669                   sd->pin_item->item->w = itb->w;
2670                   sd->pin_item->item->scrl_x = itb->x - sd->pan_x + ox;
2671                   sd->pin_item->item->scrl_y = itb->y - sd->pan_y + oy;
2672                   _pin_item_recalc(sd->pin_item);
2673                }
2674           }
2675         in += itb->vis_count;
2676      }
2677    if ((!sd->reorder_it) || (sd->reorder_pan_move))
2678      _group_items_recalc(sd);
2679    if ((sd->reorder_mode) && (sd->reorder_it))
2680      {
2681         if (sd->pan_y != sd->reorder_old_pan_y)
2682           sd->reorder_pan_move = EINA_TRUE;
2683         else sd->reorder_pan_move = EINA_FALSE;
2684 
2685         evas_object_raise(sd->VIEW(reorder_it));
2686         evas_object_stack_below(sd->VIEW(reorder_it), sd->stack[1]);
2687         sd->reorder_old_pan_y = sd->pan_y;
2688         sd->start_time = ecore_loop_time_get();
2689      }
2690 
2691    if (!sd->tree_effect_enabled ||
2692        (sd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_NONE))
2693      _item_auto_scroll(sd);
2694 
2695    elm_interface_scrollable_content_pos_get((sd)->obj, &vx, &vy);
2696    elm_interface_scrollable_content_viewport_geometry_get
2697          ((sd)->obj, NULL, NULL, &vw, &vh);
2698 
2699    if (sd->reorder_fast == 1)
2700       elm_interface_scrollable_content_region_show((sd)->obj, vx, vy - 10, vw, vh);
2701    else if (sd->reorder_fast == -1)
2702       elm_interface_scrollable_content_region_show((sd)->obj, vx, vy + 10, vw, vh);
2703 
2704    if (sd->focused_item && !sd->item_loop_enable)
2705      _elm_widget_focus_highlight_start(psd->wobj);
2706 
2707    EINA_LIST_FOREACH(sd->group_items, l, git)
2708      {
2709         git->item->want_realize = EINA_FALSE;
2710         if (git->realized) evas_object_raise(VIEW(git));
2711      }
2712 
2713    if (sd->pin_item)
2714      evas_object_raise(VIEW(sd->pin_item));
2715    //update item before the render to prevent delayed update by job.
2716    if (sd->update_job)
2717      {
2718         ELM_SAFE_FREE(sd->update_job, ecore_job_del);
2719         _update_job(sd->obj);
2720      }
2721 
2722    evas_event_thaw(e);
2723    evas_event_thaw_eval(e);
2724 
2725    efl_event_callback_legacy_call
2726          (psd->wobj, ELM_INTERFACE_SCROLLABLE_EVENT_CHANGED, NULL);
2727 }
2728 
2729 EOLIAN static void
_elm_genlist_pan_efl_object_destructor(Eo * obj,Elm_Genlist_Pan_Data * psd)2730 _elm_genlist_pan_efl_object_destructor(Eo *obj, Elm_Genlist_Pan_Data *psd)
2731 {
2732    efl_data_unref(psd->wobj, psd->wsd);
2733    efl_destructor(efl_super(obj, MY_PAN_CLASS));
2734 }
2735 
2736 EOLIAN static void
_elm_genlist_pan_class_constructor(Efl_Class * klass)2737 _elm_genlist_pan_class_constructor(Efl_Class *klass)
2738 {
2739       evas_smart_legacy_type_register(MY_PAN_CLASS_NAME_LEGACY, klass);
2740 }
2741 
2742 static Eina_Bool
_item_multi_select_up(Elm_Genlist_Data * sd)2743 _item_multi_select_up(Elm_Genlist_Data *sd)
2744 {
2745    Elm_Object_Item *eo_prev;
2746 
2747    if (!sd->selected) return EINA_FALSE;
2748    if (!sd->multi) return EINA_FALSE;
2749 
2750    eo_prev = elm_genlist_item_prev_get(sd->last_selected_item);
2751    while (eo_prev)
2752      {
2753         ELM_GENLIST_ITEM_DATA_GET(eo_prev, prev);
2754         if ((!_is_no_select(prev)) &&
2755             (!elm_object_item_disabled_get(eo_prev)) && (!prev->hide))
2756           break;
2757         eo_prev = EO_OBJ(ELM_GEN_ITEM_PREV(prev));
2758      }
2759    if (!eo_prev) return EINA_TRUE;
2760 
2761    if (elm_genlist_item_selected_get(eo_prev))
2762      {
2763         elm_genlist_item_selected_set(sd->last_selected_item, EINA_FALSE);
2764         sd->last_selected_item = eo_prev;
2765      }
2766    else
2767      {
2768         elm_genlist_item_selected_set(eo_prev, EINA_TRUE);
2769      }
2770    return EINA_TRUE;
2771 }
2772 
2773 static Eina_Bool
_item_multi_select_down(Elm_Genlist_Data * sd)2774 _item_multi_select_down(Elm_Genlist_Data *sd)
2775 {
2776    Elm_Object_Item *eo_next;
2777 
2778    if (!sd->selected) return EINA_FALSE;
2779    if (!sd->multi) return EINA_FALSE;
2780 
2781    eo_next = elm_genlist_item_next_get(sd->last_selected_item);
2782    while ((eo_next))
2783      {
2784         ELM_GENLIST_ITEM_DATA_GET(eo_next, next);
2785         if ((!_is_no_select(next)) &&
2786             (!elm_object_item_disabled_get(eo_next)) && (!next->hide))
2787           break;
2788         eo_next = EO_OBJ(ELM_GEN_ITEM_NEXT(next));
2789      }
2790    if (!eo_next) return EINA_TRUE;
2791 
2792    if (elm_genlist_item_selected_get(eo_next))
2793      {
2794         elm_genlist_item_selected_set(sd->last_selected_item, EINA_FALSE);
2795         sd->last_selected_item = eo_next;
2796      }
2797    else
2798      {
2799         elm_genlist_item_selected_set(eo_next, EINA_TRUE);
2800      }
2801 
2802    return EINA_TRUE;
2803 }
2804 
2805 static Eina_Bool
_all_items_deselect(Elm_Genlist_Data * sd)2806 _all_items_deselect(Elm_Genlist_Data *sd)
2807 {
2808    if (!sd->selected) return EINA_FALSE;
2809 
2810    sd->deselecting = eina_list_clone(sd->selected);
2811    while (sd->deselecting)
2812      {
2813         Elm_Object_Item *it = eina_list_data_get(sd->deselecting);
2814 
2815         sd->deselecting = eina_list_remove_list(sd->deselecting, sd->deselecting);
2816         elm_genlist_item_selected_set(it, EINA_FALSE);
2817      }
2818 
2819    return EINA_TRUE;
2820 }
2821 
2822 static Eina_Bool
_item_single_select_up(Elm_Genlist_Data * sd)2823 _item_single_select_up(Elm_Genlist_Data *sd)
2824 {
2825    Elm_Gen_Item *prev = NULL;
2826 
2827    if (!sd->selected)
2828      prev = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
2829    else
2830      {
2831         Elm_Object_Item *eo_prev = elm_genlist_item_prev_get
2832            (sd->last_selected_item);
2833         prev = efl_data_scope_get(eo_prev, ELM_GENLIST_ITEM_CLASS);
2834      }
2835 
2836    while (prev)
2837      {
2838         if ((!_is_no_select(prev)) &&
2839             (!elm_object_item_disabled_get(EO_OBJ(prev))) && (!prev->hide))
2840           break;
2841         prev = ELM_GEN_ITEM_PREV(prev);
2842      }
2843 
2844    if (!prev) return EINA_FALSE;
2845 
2846    _all_items_deselect(sd);
2847 
2848    elm_genlist_item_selected_set(EO_OBJ(prev), EINA_TRUE);
2849    return EINA_TRUE;
2850 }
2851 
2852 static Eina_Bool
_item_single_select_down(Elm_Genlist_Data * sd)2853 _item_single_select_down(Elm_Genlist_Data *sd)
2854 {
2855    Elm_Gen_Item *next = NULL;
2856    Elm_Object_Item *eo_next = NULL;
2857 
2858    if (!sd->selected)
2859      next = ELM_GEN_ITEM_FROM_INLIST(sd->items);
2860    else
2861      {
2862         eo_next = elm_genlist_item_next_get(sd->last_selected_item);
2863         next = efl_data_scope_get(eo_next, ELM_GENLIST_ITEM_CLASS);
2864      }
2865 
2866    while (next)
2867      {
2868         if ((!_is_no_select(next)) &&
2869             (!elm_object_item_disabled_get(EO_OBJ(next))) && (!next->hide))
2870           break;
2871         next = ELM_GEN_ITEM_NEXT(next);
2872      }
2873 
2874    if (!next) return EINA_FALSE;
2875 
2876    _all_items_deselect(sd);
2877 
2878    elm_genlist_item_selected_set(EO_OBJ(next), EINA_TRUE);
2879 
2880    return EINA_TRUE;
2881 }
2882 
2883 static void
_elm_genlist_item_focused(Elm_Object_Item * eo_it)2884 _elm_genlist_item_focused(Elm_Object_Item *eo_it)
2885 {
2886    ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
2887    Evas_Object *obj = WIDGET(it);
2888    ELM_GENLIST_DATA_GET(obj, sd);
2889 
2890    if (_is_no_select(it) ||
2891        (eo_it == sd->focused_item) ||
2892        (elm_wdg_item_disabled_get(eo_it)))
2893      return;
2894 
2895    if (it != sd->pin_item)
2896      {
2897         switch (_elm_config->focus_autoscroll_mode)
2898           {
2899            case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
2900               elm_genlist_item_show(eo_it,
2901                                     ELM_GENLIST_ITEM_SCROLLTO_IN);
2902               break;
2903            case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
2904               elm_genlist_item_bring_in(eo_it,
2905                                         ELM_GENLIST_ITEM_SCROLLTO_IN);
2906               break;
2907            default:
2908               break;
2909           }
2910      }
2911 
2912    sd->focused_item = eo_it;
2913 
2914    if (it->realized)
2915      _elm_genlist_item_focus_update(it);
2916    efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_ITEM_FOCUSED, eo_it);
2917    if (_elm_config->atspi_mode)
2918      efl_access_state_changed_signal_emit(eo_it, EFL_ACCESS_STATE_TYPE_FOCUSED, EINA_TRUE);
2919 }
2920 
2921 static void
_elm_genlist_item_unfocused(Elm_Object_Item * eo_it)2922 _elm_genlist_item_unfocused(Elm_Object_Item *eo_it)
2923 {
2924    if (!eo_it) return;
2925 
2926    ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
2927    Evas_Object *obj = WIDGET(it);
2928    Evas_Object *win = efl_provider_find(obj, EFL_UI_WIN_CLASS);
2929    ELM_GENLIST_DATA_GET(obj, sd);
2930 
2931    if (_is_no_select(it))
2932      return;
2933 
2934    if ((!sd->focused_item) ||
2935        (eo_it != sd->focused_item))
2936      return;
2937 
2938    if (elm_win_focus_highlight_enabled_get(win))
2939      {
2940         ELM_GENLIST_ITEM_DATA_GET(sd->focused_item, focus_it);
2941         edje_object_signal_emit(VIEW(focus_it), SIGNAL_UNFOCUSED, "elm");
2942      }
2943 
2944    sd->focused_item = NULL;
2945    efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_ITEM_UNFOCUSED, eo_it);
2946    if (_elm_config->atspi_mode)
2947      efl_access_state_changed_signal_emit(eo_it, EFL_ACCESS_STATE_TYPE_FOCUSED, EINA_FALSE);
2948 }
2949 
2950 static Eina_Bool
_item_focused_next(Evas_Object * obj,Elm_Focus_Direction dir)2951 _item_focused_next(Evas_Object *obj, Elm_Focus_Direction dir)
2952 {
2953    ELM_GENLIST_DATA_GET(obj, sd);
2954    Elm_Gen_Item *next;
2955    Elm_Object_Item *eo_next;
2956    Elm_Object_Item *eo_first_item;
2957    Elm_Object_Item *eo_last_item;
2958 
2959    if (!sd->focused_item)
2960      {
2961         if (dir == ELM_FOCUS_UP)
2962           next = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
2963         else if (dir == ELM_FOCUS_DOWN)
2964           next = ELM_GEN_ITEM_FROM_INLIST(sd->items);
2965         else
2966           return EINA_FALSE;
2967 
2968         while ((next) &&
2969                ((elm_wdg_item_disabled_get(EO_OBJ(next))) ||
2970                (_is_no_select(next))))
2971           if (!next->hide) next = ELM_GEN_ITEM_NEXT(next);
2972      }
2973    else
2974      {
2975         ELM_GENLIST_ITEM_DATA_GET(sd->focused_item, focus_it);
2976         if (dir == ELM_FOCUS_UP)
2977           {
2978              eo_first_item = elm_genlist_first_item_get(WIDGET(focus_it));
2979              if (eo_first_item == sd->focused_item) return EINA_FALSE;
2980              eo_next = elm_genlist_item_prev_get(sd->focused_item);
2981              next = efl_data_scope_get(eo_next, ELM_GENLIST_ITEM_CLASS);
2982 
2983              while ((next) &&
2984                     ((elm_wdg_item_disabled_get(eo_next)) ||
2985                     (_is_no_select(next))))
2986                {
2987                   eo_next = elm_genlist_item_prev_get(eo_next);
2988                   next = efl_data_scope_get(eo_next, ELM_GENLIST_ITEM_CLASS);
2989                }
2990           }
2991         else if (dir == ELM_FOCUS_DOWN)
2992           {
2993              eo_last_item = elm_genlist_last_item_get(WIDGET(focus_it));
2994              if (eo_last_item == sd->focused_item) return EINA_FALSE;
2995              eo_next = elm_genlist_item_next_get(sd->focused_item);
2996              next = efl_data_scope_get(eo_next, ELM_GENLIST_ITEM_CLASS);
2997 
2998              while ((next) &&
2999                     ((elm_wdg_item_disabled_get(eo_next)) ||
3000                     (_is_no_select(next))))
3001                {
3002                   eo_next = elm_genlist_item_next_get(eo_next);
3003                   next = efl_data_scope_get(eo_next, ELM_GENLIST_ITEM_CLASS);
3004                }
3005           }
3006         else
3007           return EINA_FALSE;
3008 
3009         if (!next) return EINA_FALSE;
3010      }
3011 
3012    elm_object_item_focus_set(EO_OBJ(next), EINA_TRUE);
3013 
3014    return EINA_TRUE;
3015 }
3016 
3017 static void
_elm_genlist_item_content_focus_set(Elm_Gen_Item * it,Elm_Focus_Direction dir)3018 _elm_genlist_item_content_focus_set(Elm_Gen_Item *it, Elm_Focus_Direction dir)
3019 {
3020    Evas_Object *focused_obj = NULL;
3021    Eina_List *l;
3022    if (!it) return;
3023 
3024    if (!it->item->wsd->focus_on_selection_enabled) return;
3025 
3026    if (!it->item_focus_chain)
3027      {
3028         elm_object_focus_set(VIEW(it), EINA_TRUE);
3029         return;
3030      }
3031 
3032    EINA_LIST_FOREACH(it->item_focus_chain, l, focused_obj)
3033      if (elm_object_focus_get(focused_obj)) break;
3034 
3035    /* FOCUS-FIXME
3036    if (focused_obj && (dir != ELM_FOCUS_PREVIOUS))
3037      {
3038         Evas_Object *nextfocus;
3039         Elm_Object_Item *nextfocus_item;
3040         if (efl_ui_widget_focus_next_get(focused_obj, dir, &nextfocus, &nextfocus_item))
3041           {
3042              if (nextfocus_item)
3043                elm_object_item_focus_set(nextfocus_item, EINA_TRUE);
3044              else
3045                elm_object_focus_set(nextfocus, EINA_TRUE);
3046              return;
3047           }
3048      }
3049    */
3050 
3051    if (!l) l = it->item_focus_chain;
3052 
3053    if (dir == ELM_FOCUS_RIGHT)
3054      {
3055         l = eina_list_next(l);
3056         if (!l) l = it->item_focus_chain;
3057      }
3058    else if (dir == ELM_FOCUS_LEFT)
3059      {
3060         l = eina_list_prev(l);
3061         if (!l) l = eina_list_last(it->item_focus_chain);
3062      }
3063 
3064    elm_object_focus_set(eina_list_data_get(l), EINA_TRUE);
3065 }
3066 
3067 static Eina_Bool
_key_action_move_dir(Evas_Object * obj,Elm_Focus_Direction dir,Eina_Bool multi)3068 _key_action_move_dir(Evas_Object *obj, Elm_Focus_Direction dir, Eina_Bool multi)
3069 {
3070    ELM_GENLIST_DATA_GET(obj, sd);
3071    Elm_Object_Item *it = NULL;
3072    Eina_Bool ret = EINA_FALSE;
3073    Evas_Coord v = 0;
3074    Evas_Coord min = 0;
3075    Eina_Bool focus_only = EINA_FALSE;
3076 
3077    // get content size and viewport size
3078    elm_interface_scrollable_content_viewport_geometry_get
3079          (obj, NULL, NULL, NULL, &v);
3080    elm_interface_scrollable_content_size_get(obj, NULL, &min);
3081 
3082    if (_elm_config->item_select_on_focus_disable)
3083      {
3084         ret = _item_focused_next(obj, dir);
3085      }
3086    else
3087      {
3088         if (multi)
3089           {
3090              if (dir == ELM_FOCUS_UP)
3091                ret = _item_multi_select_up(sd);
3092              else if (dir == ELM_FOCUS_DOWN)
3093                ret = _item_multi_select_down(sd);
3094           }
3095         else
3096           {
3097              if ((sd->focused_item) && (dir == ELM_FOCUS_UP))
3098                ret = _item_single_select_up(sd);
3099              else if (dir == ELM_FOCUS_DOWN)
3100                ret = _item_single_select_down(sd);
3101           }
3102      }
3103    if (ret)
3104      return EINA_TRUE;
3105 
3106    focus_only = _elm_config->item_select_on_focus_disable;
3107    // handle item loop feature
3108    if (sd->item_loop_enable && !sd->item_looping_on)
3109      {
3110         if (min < v)
3111           {
3112              if (dir == ELM_FOCUS_UP)
3113                {
3114                   elm_layout_signal_emit(obj, "elm,action,looping,up", "elm");
3115                   sd->item_looping_on = EINA_TRUE;
3116                }
3117              else if (dir == ELM_FOCUS_DOWN)
3118                {
3119                   elm_layout_signal_emit(obj, "elm,action,looping,down", "elm");
3120                   sd->item_looping_on = EINA_TRUE;
3121                }
3122           }
3123         else
3124           {
3125              if (dir == ELM_FOCUS_UP)
3126                {
3127                   it = elm_genlist_last_item_get(obj);
3128                   ELM_GENLIST_ITEM_DATA_GET(it, gen_it);
3129                   while (_is_no_select(gen_it) || elm_wdg_item_disabled_get(it))
3130                     it = elm_genlist_item_prev_get(it);
3131                }
3132             else if (dir == ELM_FOCUS_DOWN)
3133               {
3134                  it = elm_genlist_first_item_get(obj);
3135                  ELM_GENLIST_ITEM_DATA_GET(it, gen_it);
3136                  while (_is_no_select(gen_it) || elm_wdg_item_disabled_get(it))
3137                    it = elm_genlist_item_next_get(it);
3138               }
3139 
3140              if (it && focus_only)
3141                elm_object_item_focus_set(it, EINA_TRUE);
3142              else if (it)
3143                elm_genlist_item_selected_set(it, EINA_TRUE);
3144           }
3145         return EINA_TRUE;
3146      }
3147    else if (sd->item_looping_on)
3148      return EINA_TRUE;
3149 
3150    return EINA_FALSE;
3151 }
3152 
3153 static Eina_Bool
_key_action_move(Evas_Object * obj,const char * params)3154 _key_action_move(Evas_Object *obj, const char *params)
3155 {
3156    ELM_GENLIST_DATA_GET(obj, sd);
3157    const char *dir = params;
3158 
3159    Evas_Coord x = 0;
3160    Evas_Coord y = 0;
3161    Evas_Coord v_w = 0;
3162    Evas_Coord v_h = 0;
3163    Evas_Coord step_x = 0;
3164    Evas_Coord step_y = 0;
3165    Evas_Coord page_x = 0;
3166    Evas_Coord page_y = 0;
3167    Elm_Object_Item *it = NULL;
3168    Evas_Coord pan_max_x = 0, pan_max_y = 0;
3169 
3170    if (!sd->items) return EINA_FALSE;
3171    elm_interface_scrollable_content_pos_get(obj, &x, &y);
3172    elm_interface_scrollable_step_size_get(obj, &step_x, &step_y);
3173    elm_interface_scrollable_page_size_get(obj, &page_x, &page_y);
3174    elm_interface_scrollable_content_viewport_geometry_get
3175          (obj, NULL, NULL, &v_w, &v_h);
3176 
3177    _elm_widget_focus_auto_show(obj);
3178 
3179    if (!strcmp(dir, "up_multi"))
3180      {
3181         if (_key_action_move_dir(obj, ELM_FOCUS_UP, EINA_TRUE)) return EINA_TRUE;
3182         else if (_key_action_move_dir(obj, ELM_FOCUS_UP, EINA_FALSE)) return EINA_TRUE;
3183         else return EINA_FALSE;
3184      }
3185    else if (!strcmp(dir, "down_multi"))
3186      {
3187         if (_key_action_move_dir(obj, ELM_FOCUS_DOWN, EINA_TRUE)) return EINA_TRUE;
3188         else if (_key_action_move_dir(obj, ELM_FOCUS_DOWN, EINA_FALSE)) return EINA_TRUE;
3189         else return EINA_FALSE;
3190      }
3191    else if (!strcmp(dir, "first"))
3192      {
3193         it = elm_genlist_first_item_get(obj);
3194         if (it)
3195           {
3196              if (_elm_config->item_select_on_focus_disable)
3197                {
3198                   elm_object_item_focus_set(it, EINA_TRUE);
3199                   elm_genlist_item_show(it, ELM_GENLIST_ITEM_SCROLLTO_TOP);
3200                }
3201              else
3202                {
3203                   elm_genlist_item_selected_set(it, EINA_TRUE);
3204                }
3205              return EINA_TRUE;
3206           }
3207      }
3208    else if (!strcmp(dir, "last"))
3209      {
3210         it = elm_genlist_last_item_get(obj);
3211         if (it)
3212           {
3213              if (_elm_config->item_select_on_focus_disable)
3214                {
3215                   elm_object_item_focus_set(it, EINA_TRUE);
3216                   elm_genlist_item_show(it, ELM_GENLIST_ITEM_SCROLLTO_BOTTOM);
3217                }
3218              else
3219                {
3220                   elm_genlist_item_selected_set(it, EINA_TRUE);
3221                }
3222              return EINA_TRUE;
3223           }
3224      }
3225    else if (!strcmp(dir, "prior"))
3226      {
3227         if (page_y < 0)
3228           y -= -(page_y * v_h) / 100;
3229         else
3230           y -= page_y;
3231      }
3232    else if (!strcmp(dir, "next"))
3233      {
3234         if (page_y < 0)
3235           y += -(page_y * v_h) / 100;
3236         else
3237           y += page_y;
3238      }
3239    else return EINA_FALSE;
3240 
3241    elm_obj_pan_pos_max_get(sd->pan_obj, &pan_max_x, &pan_max_y);
3242    if (x < 0)
3243      x = 0;
3244    else if (x > pan_max_x)
3245      x = pan_max_x;
3246    if (y < 0)
3247      y = 0;
3248    else if (y > pan_max_y)
3249      y = pan_max_y;
3250 
3251    elm_interface_scrollable_content_pos_set(obj, x, y, EINA_TRUE);
3252 
3253    return EINA_TRUE;
3254 }
3255 
3256 static Eina_Bool
_key_action_select(Evas_Object * obj,const char * params)3257 _key_action_select(Evas_Object *obj, const char *params)
3258 {
3259    Elm_Object_Item *eo_it = NULL;
3260 
3261    ELM_GENLIST_DATA_GET(obj, sd);
3262    if (!sd->items) return EINA_FALSE;
3263 
3264    eo_it = elm_object_focused_item_get(obj);
3265    if (!eo_it) return EINA_TRUE;
3266    elm_genlist_item_expanded_set(eo_it, !elm_genlist_item_expanded_get(eo_it));
3267    ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
3268 
3269    if (sd->multi &&
3270        ((sd->multi_select_mode != ELM_OBJECT_MULTI_SELECT_MODE_WITH_CONTROL) ||
3271         (!strcmp(params, "multi"))))
3272      {
3273         if (!it->selected)
3274           {
3275              _item_highlight(it);
3276              if (_item_select(it)) goto deleted;
3277           }
3278         else
3279          _item_unselect(it);
3280      }
3281    else
3282      {
3283         if (!it->selected)
3284           {
3285              while (sd->selected)
3286                {
3287                   Elm_Object_Item *eo_sel = sd->selected->data;
3288                   Elm_Gen_Item *sel = efl_data_scope_get(eo_sel, ELM_GENLIST_ITEM_CLASS);
3289                   _item_unselect(sel);
3290                }
3291           }
3292         else
3293           {
3294              const Eina_List *l, *l_next;
3295              Elm_Object_Item *eo_it2;
3296 
3297              EINA_LIST_FOREACH_SAFE(sd->selected, l, l_next, eo_it2)
3298                {
3299                   ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
3300                   if (it2 != it)
3301                     _item_unselect(it2);
3302                }
3303           }
3304         _item_highlight(it);
3305         if (_item_select(it)) goto deleted;
3306      }
3307 
3308    efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_ACTIVATED, EO_OBJ(it));
3309 
3310    return EINA_TRUE;
3311 
3312 deleted:
3313    return EINA_FALSE;
3314 }
3315 
3316 static Eina_Bool
_key_action_escape(Evas_Object * obj,const char * params EINA_UNUSED)3317 _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED)
3318 {
3319    ELM_GENLIST_DATA_GET(obj, sd);
3320 
3321    if (!_all_items_deselect(sd)) return EINA_FALSE;
3322    return EINA_TRUE;
3323 }
3324 
3325 EOLIAN static Eina_Bool
_elm_genlist_efl_ui_widget_widget_sub_object_add(Eo * obj,Elm_Genlist_Data * _pd EINA_UNUSED,Evas_Object * sobj)3326 _elm_genlist_efl_ui_widget_widget_sub_object_add(Eo *obj, Elm_Genlist_Data *_pd EINA_UNUSED, Evas_Object *sobj)
3327 {
3328    /* skipping layout's code, which registers size hint changing
3329     * callback on sub objects. this is here because items'
3330     * content_get() routines may change hints on the objects after
3331     * creation, thus issuing TOO MANY sizing_eval()'s here. they are
3332     * not needed at here anyway, so let's skip listening to those
3333     * hints changes */
3334    return elm_widget_sub_object_add(efl_cast(obj, EFL_UI_WIDGET_CLASS), sobj);
3335 }
3336 
3337 EOLIAN static Eina_Bool
_elm_genlist_efl_ui_widget_widget_sub_object_del(Eo * obj,Elm_Genlist_Data * sd,Evas_Object * sobj)3338 _elm_genlist_efl_ui_widget_widget_sub_object_del(Eo *obj, Elm_Genlist_Data *sd, Evas_Object *sobj)
3339 {
3340    Eina_Bool int_ret = EINA_FALSE;
3341 
3342    /* XXX: hack -- also skipping sizing recalculation on
3343     * sub-object-del. genlist's crazy code paths (like groups and
3344     * such) seem to issue a whole lot of deletions and Evas bitches
3345     * about too many recalculations */
3346    sd->on_sub_del = EINA_TRUE;
3347    int_ret = elm_widget_sub_object_del(efl_super(obj, MY_CLASS), sobj);
3348    sd->on_sub_del = EINA_FALSE;
3349    return int_ret;
3350 }
3351 
3352 /*
3353  * This function searches the nearest visible item based on the given item.
3354  * If the given item is in the genlist viewport, this returns the given item.
3355  * Or this searches the realized items and checks the nearest fully visible item
3356  * according to the given item's position.
3357  */
3358 static Elm_Object_Item *
_elm_genlist_nearest_visible_item_get(Evas_Object * obj,Elm_Object_Item * eo_it)3359 _elm_genlist_nearest_visible_item_get(Evas_Object *obj, Elm_Object_Item *eo_it)
3360 {
3361    Evas_Coord vx = 0, vy = 0, vw = 0, vh = 0; // genlist viewport geometry
3362    Evas_Coord ix = 0, iy = 0, iw = 0, ih = 0; // given item geometry
3363    Evas_Coord cx = 0, cy = 0, cw = 0, ch = 0; // candidate item geometry
3364    Eina_List *item_list = NULL, *l = NULL;
3365    Elm_Object_Item *first_item, *eo_item = NULL;
3366    ELM_GENLIST_DATA_GET(obj, sd);
3367    Eina_Bool search_next = EINA_FALSE;
3368 
3369    if (!eo_it) return NULL;
3370    ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
3371 
3372    evas_object_geometry_get(sd->pan_obj, &vx, &vy, &vw, &vh);
3373 
3374    if (it->realized)
3375      {
3376         evas_object_geometry_get(VIEW(it), &ix, &iy, &iw, &ih);
3377 
3378         if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, ix, iy, iw, ih))
3379           {
3380              if (!elm_object_item_disabled_get(eo_it))
3381                return eo_it;
3382              else
3383                search_next = EINA_TRUE;
3384           }
3385      }
3386 
3387    item_list = elm_genlist_realized_items_get(obj);
3388    /* if first realized item is before parameter item then parameter item is
3389     * off viewport towards bottom: start at end of list */
3390    first_item = eina_list_data_get(item_list);
3391    ELM_GENLIST_ITEM_DATA_GET(first_item, first_it);
3392 
3393    if ((iy < vy) || search_next || (!first_it) || (first_it->position > it->position))
3394      {
3395         EINA_LIST_FOREACH(item_list, l, eo_item)
3396           {
3397              ELM_GENLIST_ITEM_DATA_GET(eo_item, item);
3398              evas_object_geometry_get(VIEW(item), &cx, &cy, &cw, &ch);
3399              if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, cx, cy, cw, ch) &&
3400                  !elm_object_item_disabled_get(eo_item))
3401                {
3402                   eina_list_free(item_list);
3403                   return eo_item;
3404                }
3405           }
3406      }
3407    else
3408      {
3409         EINA_LIST_REVERSE_FOREACH(item_list, l, eo_item)
3410           {
3411              ELM_GENLIST_ITEM_DATA_GET(eo_item, item);
3412              evas_object_geometry_get(VIEW(item), &cx, &cy, &cw, &ch);
3413              if (ELM_RECTS_INCLUDE(vx, vy, vw, vh, cx, cy, cw, ch) &&
3414                  !elm_object_item_disabled_get(eo_item))
3415                {
3416                   eina_list_free(item_list);
3417                   return eo_item;
3418                }
3419           }
3420      }
3421    eina_list_free(item_list);
3422 
3423    return it->realized ? eo_it : NULL;
3424 }
3425 
3426 EOLIAN static void
_elm_genlist_efl_ui_focus_manager_setup_on_first_touch(Eo * obj,Elm_Genlist_Data * sd,Efl_Ui_Focus_Direction direction EINA_UNUSED,Efl_Ui_Focus_Object * entry EINA_UNUSED)3427 _elm_genlist_efl_ui_focus_manager_setup_on_first_touch(Eo *obj, Elm_Genlist_Data *sd, Efl_Ui_Focus_Direction direction EINA_UNUSED, Efl_Ui_Focus_Object *entry EINA_UNUSED)
3428 {
3429    Elm_Object_Item *eo_it = NULL;
3430    Eina_Bool is_sel = EINA_FALSE;
3431 
3432    if (!sd->items)
3433      {
3434         efl_ui_focus_manager_setup_on_first_touch(efl_super(obj, MY_CLASS), direction, entry);
3435      }
3436    else
3437      {
3438         if (sd->last_focused_item)
3439           eo_it = sd->last_focused_item;
3440         else if (sd->last_selected_item)
3441           eo_it = sd->last_selected_item;
3442         else if (_elm_config->first_item_focus_on_first_focus_in)
3443           {
3444              eo_it = elm_genlist_first_item_get(obj);
3445              is_sel = EINA_TRUE;
3446           }
3447 
3448         while (eo_it)
3449           {
3450              ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
3451              if ((!_is_no_select(it)) && (!elm_object_item_disabled_get(eo_it)))
3452                break;
3453              eo_it = EO_OBJ(ELM_GEN_ITEM_NEXT(it));
3454           }
3455 
3456         if (eo_it)
3457           {
3458              eo_it = _elm_genlist_nearest_visible_item_get(obj, eo_it);
3459              if (eo_it)
3460                {
3461                   if (!_elm_config->item_select_on_focus_disable && is_sel)
3462                     elm_genlist_item_selected_set(eo_it, EINA_TRUE);
3463                   else
3464                     elm_object_item_focus_set(eo_it, EINA_TRUE);
3465                  _elm_widget_focus_highlight_start(obj);
3466                  //set it again in the manager, there might be the case that the manager focus history and internal item foused logic are in different states
3467                  if (efl_ui_focus_manager_request_subchild(obj, eo_it))
3468                    efl_ui_focus_manager_focus_set(obj, eo_it);
3469                }
3470           }
3471         else
3472           {
3473              //Just set evas focus on the genlist itself, events will pass on and a other element will be taken
3474              efl_ui_focus_object_focus_set(obj, EINA_TRUE);
3475           }
3476       }
3477 }
3478 
3479 EOLIAN static Efl_Ui_Focus_Object*
_elm_genlist_efl_ui_focus_manager_manager_focus_get(const Eo * obj,EINA_UNUSED Elm_Genlist_Data * pd)3480 _elm_genlist_efl_ui_focus_manager_manager_focus_get(const Eo *obj, EINA_UNUSED Elm_Genlist_Data *pd)
3481 {
3482    Eo *focused_obj = efl_ui_focus_manager_focus_get(efl_super(obj, MY_CLASS));
3483    Eo *registered_manager = efl_ui_focus_object_focus_manager_get(obj);
3484 
3485    if (!focused_obj && efl_ui_focus_manager_redirect_get(registered_manager))
3486      return (Efl_Ui_Focus_Object*) obj;
3487 
3488    return focused_obj;
3489 }
3490 
3491 static Efl_Ui_Focus_Object*
_select_candidate(Eo * obj,EINA_UNUSED Elm_Genlist_Data * pd,Efl_Ui_Focus_Direction direction)3492 _select_candidate(Eo *obj, EINA_UNUSED Elm_Genlist_Data *pd, Efl_Ui_Focus_Direction direction)
3493 {
3494    Elm_Object_Item *first = elm_genlist_first_item_get(obj);
3495    Elm_Object_Item *last = elm_genlist_last_item_get(obj);
3496 
3497    switch(direction)
3498      {
3499         case EFL_UI_FOCUS_DIRECTION_DOWN:
3500         case EFL_UI_FOCUS_DIRECTION_RIGHT:
3501           elm_object_item_focus_set(first, EINA_TRUE);
3502           return obj;
3503         break;
3504         case EFL_UI_FOCUS_DIRECTION_UP:
3505         case EFL_UI_FOCUS_DIRECTION_LEFT:
3506           elm_object_item_focus_set(last, EINA_TRUE);
3507           return obj;
3508         break;
3509         case EFL_UI_FOCUS_DIRECTION_NEXT:
3510         case EFL_UI_FOCUS_DIRECTION_PREVIOUS:
3511           //do not go further with logical movement
3512           return NULL;
3513         break;
3514         default:
3515           ERR("Uncaught focus direction");
3516           return NULL;
3517         break;
3518      }
3519 }
3520 
3521 EOLIAN static Efl_Ui_Focus_Object*
_elm_genlist_efl_ui_focus_manager_move(Eo * obj,Elm_Genlist_Data * pd,Efl_Ui_Focus_Direction direction)3522 _elm_genlist_efl_ui_focus_manager_move(Eo *obj, Elm_Genlist_Data *pd, Efl_Ui_Focus_Direction direction)
3523 {
3524    if (efl_ui_focus_manager_focus_get(obj) == obj)
3525      {
3526         return _select_candidate(obj, pd, direction);
3527      }
3528    else
3529      {
3530         return efl_ui_focus_manager_move(efl_super(obj, MY_CLASS), direction);
3531      }
3532 }
3533 
3534 EOLIAN static Eina_Bool
_elm_genlist_efl_ui_focus_object_on_focus_update(Eo * obj,Elm_Genlist_Data * sd)3535 _elm_genlist_efl_ui_focus_object_on_focus_update(Eo *obj, Elm_Genlist_Data *sd)
3536 {
3537    Eina_Bool int_ret = EINA_FALSE;
3538 
3539    int_ret = efl_ui_focus_object_on_focus_update(efl_super(obj, MY_CLASS));
3540    if (!int_ret) return EINA_FALSE;
3541 
3542    if (efl_ui_focus_object_focus_get(obj) && (sd->items) && (sd->selected) &&
3543        (!sd->last_selected_item))
3544      {
3545         sd->last_selected_item = eina_list_data_get(sd->selected);
3546      }
3547 
3548    return EINA_TRUE;
3549 }
3550 
3551 static Eina_Bool _elm_genlist_smart_focus_next_enable = EINA_FALSE;
3552 
3553 static void
_mirrored_set(Evas_Object * obj,Eina_Bool rtl)3554 _mirrored_set(Evas_Object *obj,
3555               Eina_Bool rtl)
3556 {
3557    ELM_GENLIST_DATA_GET(obj, sd);
3558 
3559    _item_cache_zero(sd);
3560    efl_ui_mirrored_set(obj, rtl);
3561 }
3562 
3563 EOLIAN static Eina_Error
_elm_genlist_efl_ui_widget_theme_apply(Eo * obj,Elm_Genlist_Data * sd)3564 _elm_genlist_efl_ui_widget_theme_apply(Eo *obj, Elm_Genlist_Data *sd)
3565 {
3566    Item_Block *itb;
3567    Eina_Error int_ret = EFL_UI_THEME_APPLY_ERROR_GENERIC;
3568    Eina_List *l;
3569    Elm_Gen_Item *it;
3570    Evas *e;
3571 
3572    int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
3573    if (int_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC) return int_ret;
3574 
3575    elm_interface_scrollable_reset_signals(obj);
3576    e = evas_object_evas_get(obj);
3577    evas_event_freeze(e);
3578    _mirrored_set(obj, efl_ui_mirrored_get(obj));
3579 
3580    eina_hash_free_buckets(sd->size_caches);
3581    sd->minw = sd->minh = sd->realminw = 0;
3582 
3583    EINA_INLIST_FOREACH(sd->blocks, itb)
3584      {
3585         if (itb->realized) _item_block_unrealize(itb);
3586         EINA_LIST_FOREACH(itb->items, l, it)
3587           it->item->mincalcd = EINA_FALSE;
3588 
3589         itb->changed = EINA_TRUE;
3590      }
3591    if (sd->obj && efl_finalized_get(obj))
3592      efl_canvas_group_change(sd->obj);
3593    elm_layout_sizing_eval(obj);
3594    evas_event_thaw(e);
3595    evas_event_thaw_eval(e);
3596 
3597    return int_ret;
3598 }
3599 
3600 /* FIXME: take off later. maybe this show region coords belong in the
3601  * interface (new api functions, set/get)? */
3602 static void
_show_region_hook(void * data EINA_UNUSED,Evas_Object * obj,Eina_Rect r)3603 _show_region_hook(void *data EINA_UNUSED, Evas_Object *obj, Eina_Rect r)
3604 {
3605    ELM_GENLIST_DATA_GET_OR_RETURN(obj, sd);
3606 
3607    //x & y are screen coordinates, Add with pan coordinates
3608    r.x += sd->pan_x;
3609    r.y += sd->pan_y;
3610    elm_interface_scrollable_content_region_show(obj, r.x, r.y, r.w, r.h);
3611 }
3612 
3613 static void
_item_highlight(Elm_Gen_Item * it)3614 _item_highlight(Elm_Gen_Item *it)
3615 {
3616    const char *selectraise;
3617    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
3618 
3619    if (_is_no_select(it) ||
3620        (!sd->highlight) ||
3621        (it->highlighted) || elm_wdg_item_disabled_get(EO_OBJ(it)) ||
3622        (it->item->deco_it_view))
3623      return;
3624 
3625    edje_object_signal_emit(VIEW(it), SIGNAL_SELECTED, "elm");
3626    if (it->deco_all_view)
3627      edje_object_signal_emit(it->deco_all_view, SIGNAL_SELECTED, "elm");
3628    efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_HIGHLIGHTED, EO_OBJ(it));
3629 
3630    selectraise = edje_object_data_get(VIEW(it), "selectraise");
3631    if ((selectraise) && (!strcmp(selectraise, "on")))
3632      {
3633         if (it->deco_all_view) evas_object_stack_below(it->deco_all_view, sd->stack[1]);
3634         else evas_object_stack_below(VIEW(it), sd->stack[1]);
3635         if ((it->item->group_item) && (it->item->group_item->realized))
3636           evas_object_stack_above(it->item->VIEW(group_item), sd->stack[1]);
3637         if (sd->pin_item && sd->pin_item->realized)
3638           evas_object_stack_above(VIEW(sd->pin_item), sd->stack[1]);
3639      }
3640    it->highlighted = EINA_TRUE;
3641 }
3642 
3643 static void
_item_unhighlight(Elm_Gen_Item * it)3644 _item_unhighlight(Elm_Gen_Item *it)
3645 {
3646    if (!it->highlighted) return;
3647 
3648    edje_object_signal_emit(VIEW(it), SIGNAL_UNSELECTED, "elm");
3649    efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_UNHIGHLIGHTED, EO_OBJ(it));
3650    if (it->deco_all_view)
3651      edje_object_signal_emit(it->deco_all_view, SIGNAL_UNSELECTED, "elm");
3652    _item_restack(it);
3653    it->highlighted = EINA_FALSE;
3654 }
3655 
3656 static void
_item_block_position_update(Eina_Inlist * list,int idx)3657 _item_block_position_update(Eina_Inlist *list,
3658                             int idx)
3659 {
3660    Item_Block *tmp;
3661 
3662    EINA_INLIST_FOREACH(list, tmp)
3663      {
3664         tmp->position = idx++;
3665         tmp->position_update = EINA_TRUE;
3666      }
3667 }
3668 
3669 static void
_item_position_update(Eina_List * list,int idx)3670 _item_position_update(Eina_List *list,
3671                       int idx)
3672 {
3673    Elm_Gen_Item *it;
3674    Eina_List *l;
3675 
3676    EINA_LIST_FOREACH(list, l, it)
3677      {
3678         it->position = idx++;
3679         it->position_update = EINA_TRUE;
3680      }
3681 }
3682 
3683 static void
_item_block_merge(Item_Block * left,Item_Block * right)3684 _item_block_merge(Item_Block *left,
3685                   Item_Block *right)
3686 {
3687    Eina_List *l;
3688    Elm_Gen_Item *it2;
3689 
3690    EINA_LIST_FOREACH(right->items, l, it2)
3691      {
3692         if (right->realized)
3693           efl_ui_focus_manager_calc_unregister(right->sd->obj, EO_OBJ(it2));
3694         it2->item->block = left;
3695         left->count++;
3696         left->changed = EINA_TRUE;
3697         if (left->realized)
3698           efl_ui_focus_manager_calc_register_logical(right->sd->obj, EO_OBJ(it2), left->adapter, NULL);
3699      }
3700    left->items = eina_list_merge(left->items, right->items);
3701 }
3702 
3703 static void
_item_block_del(Elm_Gen_Item * it)3704 _item_block_del(Elm_Gen_Item *it)
3705 {
3706    Eina_Inlist *il;
3707    Item_Block *itb = it->item->block;
3708    Eina_Bool block_changed = EINA_FALSE;
3709    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
3710 
3711    itb->items = eina_list_remove(itb->items, it);
3712    itb->count--;
3713    itb->changed = EINA_TRUE;
3714    efl_canvas_group_change(sd->pan_obj);
3715    efl_canvas_group_change(sd->obj);
3716    if (itb->realized) efl_ui_focus_manager_calc_unregister(itb->sd->obj, EO_OBJ(it));
3717    if (itb->count < 1)
3718      {
3719         Item_Block *itbn;
3720 
3721         il = EINA_INLIST_GET(itb);
3722         itbn = (Item_Block *)(il->next);
3723         if (it->parent)
3724           {
3725              it->parent->item->items =
3726                    eina_list_remove(it->parent->item->items, EO_OBJ(it));
3727              if (!it->parent->item->items)
3728                sd->top_level_parent_items--;
3729           }
3730         else
3731           {
3732              _item_block_position_update(il->next, itb->position);
3733              sd->blocks = eina_inlist_remove(sd->blocks, il);
3734           }
3735         free(itb);
3736         if (itbn) itbn->changed = EINA_TRUE;
3737      }
3738    else
3739      {
3740         if (itb->count < (sd->max_items_per_block / 2))
3741           {
3742              Item_Block *itbp;
3743              Item_Block *itbn;
3744 
3745              il = EINA_INLIST_GET(itb);
3746              itbp = (Item_Block *)(il->prev);
3747              itbn = (Item_Block *)(il->next);
3748 
3749              /* merge block with previous */
3750              if ((itbp) &&
3751                  ((itbp->count + itb->count) <
3752                   (sd->max_items_per_block +
3753                    (sd->max_items_per_block / 2))))
3754                {
3755                   _item_block_merge(itbp, itb);
3756                   _item_block_position_update
3757                     (EINA_INLIST_GET(itb)->next, itb->position);
3758                   sd->blocks = eina_inlist_remove
3759                       (sd->blocks, EINA_INLIST_GET(itb));
3760                   free(itb);
3761                   block_changed = EINA_TRUE;
3762                }
3763              /* merge block with next */
3764              else if ((itbn) &&
3765                       ((itbn->count + itb->count) <
3766                        (sd->max_items_per_block +
3767                         (sd->max_items_per_block / 2))))
3768                {
3769                   _item_block_merge(itb, itbn);
3770                   _item_block_position_update
3771                     (EINA_INLIST_GET(itbn)->next, itbn->position);
3772                   sd->blocks =
3773                     eina_inlist_remove(sd->blocks, EINA_INLIST_GET(itbn));
3774                   free(itbn);
3775                   block_changed = EINA_TRUE;
3776                }
3777           }
3778      }
3779 
3780    if (block_changed)
3781      {
3782         sd->pan_changed = EINA_TRUE;
3783         evas_object_smart_changed(sd->pan_obj);
3784      }
3785 }
3786 
3787 static void
_decorate_all_item_unrealize(Elm_Gen_Item * it)3788 _decorate_all_item_unrealize(Elm_Gen_Item *it)
3789 {
3790    if ((!it) || (!it->item->decorate_all_item_realized)) return;
3791 
3792    edje_object_part_unswallow(it->deco_all_view, VIEW(it));
3793    evas_object_smart_member_add(VIEW(it), it->item->wsd->pan_obj);
3794    elm_widget_sub_object_add(WIDGET(it), VIEW(it));
3795    _elm_genlist_item_position_state_update(it);
3796    _elm_genlist_item_state_update(it);
3797 
3798    if (it->item->wsd->reorder_mode)
3799      {
3800         edje_object_signal_emit(VIEW(it), SIGNAL_REORDER_MODE_SET, "elm");
3801         edje_object_signal_emit(it->deco_all_view, SIGNAL_REORDER_MODE_UNSET,
3802                                 "elm");
3803      }
3804 
3805    _view_clear(it->deco_all_view, &(it->item->deco_all_texts),
3806                &(it->item->deco_all_contents));
3807 
3808    edje_object_signal_emit(VIEW(it), SIGNAL_DECORATE_DISABLED, "elm");
3809 
3810    edje_object_message_signal_process(it->deco_all_view);
3811    _item_mouse_callbacks_del(it, it->deco_all_view);
3812    _item_mouse_callbacks_add(it, VIEW(it));
3813 
3814    ELM_SAFE_FREE(it->deco_all_view, evas_object_del);
3815 
3816    it->item->decorate_all_item_realized = EINA_FALSE;
3817 }
3818 
3819 static void
_elm_genlist_item_del_not_serious(Elm_Gen_Item * it)3820 _elm_genlist_item_del_not_serious(Elm_Gen_Item *it)
3821 {
3822    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
3823    Elm_Object_Item *eo_it = EO_OBJ(it);
3824 
3825    elm_wdg_item_pre_notify_del(eo_it);
3826 
3827    if (it->selected)
3828      {
3829         sd->selected = eina_list_remove(sd->selected, EO_OBJ(it));
3830         if (sd->deselecting)
3831           sd->deselecting = eina_list_remove(sd->deselecting, it);
3832      }
3833    if (sd->last_focused_item == eo_it)
3834      sd->last_focused_item = NULL;
3835    if (sd->focused_item == eo_it)
3836      sd->focused_item = NULL;
3837    if (sd->last_selected_item == eo_it)
3838      sd->last_selected_item = NULL;
3839    if (sd->mode_item == it)
3840      sd-> mode_item = NULL;
3841 
3842    if (it->itc->func.del)
3843      it->itc->func.del((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it));
3844 }
3845 
3846 static void
_elm_genlist_item_del_serious(Elm_Gen_Item * it)3847 _elm_genlist_item_del_serious(Elm_Gen_Item *it)
3848 {
3849    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
3850 
3851    sd->item_count--;
3852    _elm_genlist_item_del_not_serious(it);
3853 
3854    sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(it));
3855    if (it->tooltip.del_cb)
3856      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
3857    ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
3858    if (it->item->type & ELM_GENLIST_ITEM_GROUP)
3859      sd->group_items = eina_list_remove(sd->group_items, it);
3860 
3861    ELM_SAFE_FREE(sd->state, eina_inlist_sorted_state_free);
3862    efl_canvas_group_change(sd->pan_obj);
3863    efl_canvas_group_change(sd->obj);
3864 
3865    ELM_SAFE_FREE(it->item, free);
3866 }
3867 
3868 static void
_item_del(Elm_Gen_Item * it)3869 _item_del(Elm_Gen_Item *it)
3870 {
3871    Evas *e;
3872    Evas_Object *obj = WIDGET(it);
3873    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
3874 
3875    e = evas_object_evas_get(obj);
3876    evas_event_freeze(e);
3877 
3878    if (it->item->rel_revs)
3879      {
3880         Elm_Gen_Item *tmp;
3881         EINA_LIST_FREE(it->item->rel_revs, tmp)
3882           {
3883              if (tmp->item->queued && !(tmp->base)->on_deletion)
3884                {
3885                   tmp->item->queued = EINA_FALSE;
3886                   sd->queue = eina_list_remove(sd->queue, tmp);
3887                   if (_item_process(sd, tmp))
3888                     _item_process_post(sd, tmp);
3889                }
3890              tmp->item->rel = NULL;
3891           }
3892      }
3893    if (it->item->rel)
3894      {
3895         it->item->rel->item->rel_revs =
3896            eina_list_remove(it->item->rel->item->rel_revs, it);
3897      }
3898    elm_genlist_item_subitems_clear(EO_OBJ(it));
3899    if (sd->show_item == it) sd->show_item = NULL;
3900    if (sd->pin_item == it) sd->pin_item = NULL;
3901    if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE);
3902    if (it->item->decorate_all_item_realized) _decorate_all_item_unrealize(it);
3903    if (it->item->block) _item_block_del(it);
3904    if (it->item->queued)
3905      sd->queue = eina_list_remove(sd->queue, it);
3906    if (sd->anchor_item == it)
3907      {
3908         sd->anchor_item = ELM_GEN_ITEM_NEXT(it);
3909         if (!sd->anchor_item)
3910           sd->anchor_item =
3911             ELM_GEN_ITEM_PREV(it);
3912      }
3913    if (sd->expanded_item == it)
3914      {
3915         if (sd->tree_effect_animator)
3916           {
3917              _item_tree_effect_finish(sd);
3918              _elm_genlist_tree_effect_stop(sd);
3919           }
3920         sd->expanded_item = NULL;
3921         sd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
3922      }
3923    if (sd->expanded_next_item == it) sd->expanded_next_item = NULL;
3924    if (sd->move_items) sd->move_items = eina_list_remove(sd->move_items, it);
3925    if (it->parent)
3926      {
3927         it->parent->item->items = eina_list_remove(it->parent->item->items, EO_OBJ(it));
3928         if (!it->parent->item->items)
3929           sd->top_level_parent_items--;
3930      }
3931    ELM_SAFE_FREE(it->item->swipe_timer, ecore_timer_del);
3932    _elm_genlist_item_del_serious(it);
3933 
3934    if (it->itc->refcount <= 1 && eina_hash_find(sd->size_caches, &(it->itc)))
3935      eina_hash_del_by_key(sd->size_caches, it->itc);
3936    elm_genlist_item_class_unref((Elm_Genlist_Item_Class *)it->itc);
3937    evas_event_thaw(e);
3938    evas_event_thaw_eval(e);
3939    if (!sd->queue) _item_scroll(sd);
3940 }
3941 
3942 static void
_item_unselect(Elm_Gen_Item * it)3943 _item_unselect(Elm_Gen_Item *it)
3944 {
3945    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
3946 
3947    _item_unhighlight(it); /* unhighlight the item first */
3948    if (!it->selected) return; /* then check whether the item is selected */
3949 
3950   if (it->item->wsd->focus_on_selection_enabled)
3951      {
3952         Evas_Object* eobj;
3953         Eina_List* l;
3954         EINA_LIST_FOREACH(it->item_focus_chain, l, eobj)
3955           elm_object_focus_set(eobj, EINA_FALSE);
3956      }
3957 
3958    it->selected = EINA_FALSE;
3959    sd->selected = eina_list_remove(sd->selected, EO_OBJ(it));
3960    evas_object_smart_callback_call
3961           (WIDGET(it), "unselected", EO_OBJ(it));
3962    if (_elm_config->atspi_mode)
3963      efl_access_state_changed_signal_emit(EO_OBJ(it), EFL_ACCESS_STATE_TYPE_SELECTED, EINA_FALSE);
3964 }
3965 
3966 static void
_item_mouse_in_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)3967 _item_mouse_in_cb(void *data,
3968                   Evas *evas EINA_UNUSED,
3969                   Evas_Object *obj EINA_UNUSED,
3970                   void *event_info EINA_UNUSED)
3971 {
3972    Elm_Gen_Item *it = data;
3973    if (!elm_object_item_disabled_get(EO_OBJ(it)) &&
3974        (_elm_config->focus_move_policy == ELM_FOCUS_MOVE_POLICY_IN))
3975      elm_object_item_focus_set(EO_OBJ(it), EINA_TRUE);
3976 }
3977 
3978 static void
_item_mouse_move_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj,void * event_info)3979 _item_mouse_move_cb(void *data,
3980                     Evas *evas EINA_UNUSED,
3981                     Evas_Object *obj,
3982                     void *event_info)
3983 {
3984    Elm_Gen_Item *it = data;
3985    Evas_Event_Mouse_Move *ev = event_info;
3986    Evas_Coord ox, oy, ow, oh, it_scrl_y, y_pos;
3987    Evas_Coord minw = 0, minh = 0, x, y, w, h, dx, dy, adx, ady;
3988    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
3989    Elm_Object_Item *eo_it = EO_OBJ(it);
3990 
3991    evas_object_geometry_get(obj, &x, &y, &w, &h);
3992    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
3993      {
3994         if (!sd->on_hold)
3995           {
3996              sd->on_hold = EINA_TRUE;
3997              if ((!sd->wasselected) && (!it->flipped))
3998                _item_unselect(it);
3999           }
4000      }
4001    else if (it->down && ELM_RECTS_POINT_OUT(x, y, w, h, ev->cur.canvas.x, ev->cur.canvas.y) &&
4002             !sd->reorder_it)
4003      {
4004         ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
4005         if ((!sd->wasselected) && (!it->flipped))
4006           _item_unselect(it);
4007         it->base->still_in = EINA_FALSE;
4008      }
4009 
4010    if (sd->multi_touched)
4011      {
4012         sd->cur_x = ev->cur.canvas.x;
4013         sd->cur_y = ev->cur.canvas.y;
4014         return;
4015      }
4016    if ((it->dragging) && (it->down))
4017      {
4018         if (sd->movements == SWIPE_MOVES)
4019           sd->swipe = EINA_TRUE;
4020         else
4021           {
4022              sd->history[sd->movements].x = ev->cur.canvas.x;
4023              sd->history[sd->movements].y = ev->cur.canvas.y;
4024              if (abs((sd->history[sd->movements].x -
4025                       sd->history[0].x)) > 40)
4026                sd->swipe = EINA_TRUE;
4027              else
4028                sd->movements++;
4029           }
4030         ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
4031         evas_object_smart_callback_call(WIDGET(it), "drag", eo_it);
4032         return;
4033      }
4034    if ((!it->down) || (sd->longpressed))
4035      {
4036         ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
4037         if ((sd->reorder_mode) && (sd->reorder_it))
4038           {
4039              Eina_Bool changed;
4040              evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
4041 
4042              if (ev->cur.canvas.y < (oy + (sd->reorder_it->item->h / 2)))
4043                 sd->reorder_fast = 1;
4044              else if (ev->cur.canvas.y > (oy + oh - (sd->reorder_it->item->h  / 2)))
4045                 sd->reorder_fast = -1;
4046              else sd->reorder_fast = 0;
4047 
4048              it_scrl_y = ev->cur.canvas.y - sd->reorder_it->dy;
4049 
4050              if (!sd->reorder_start_y)
4051                sd->reorder_start_y = it->item->block->y + it->y;
4052 
4053              if (it_scrl_y < oy)
4054                y_pos = oy;
4055              else if (it_scrl_y + sd->reorder_it->item->h > oy + oh)
4056                y_pos = oy + oh - sd->reorder_it->item->h;
4057              else
4058                y_pos = it_scrl_y;
4059 
4060              if (it->deco_all_view)
4061                changed = _item_position(it, it->deco_all_view, it->item->scrl_x, y_pos);
4062              else
4063                changed = _item_position(it, VIEW(it), it->item->scrl_x, y_pos);
4064 
4065              efl_canvas_group_change(sd->obj);
4066              if (changed)
4067                efl_canvas_group_change(sd->pan_obj);
4068           }
4069         return;
4070      }
4071    if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
4072      elm_coords_finger_size_adjust(1, &minw, 1, &minh);
4073 
4074    evas_object_geometry_get(obj, &x, &y, &w, &h);
4075    x = ev->cur.canvas.x - x;
4076    y = ev->cur.canvas.y - y;
4077    dx = x - it->dx;
4078    adx = dx;
4079    if (adx < 0) adx = -dx;
4080 
4081    dy = y - it->dy;
4082    ady = dy;
4083    if (ady < 0) ady = -dy;
4084 
4085    minw /= 2;
4086    minh /= 2;
4087 
4088    // gah! annoying drag detection - leave this alone
4089    if (h < w)
4090      {
4091         if (minw < h) minw = h;
4092         if (minh < h) minh = h;
4093      }
4094    else
4095      {
4096         if (minw < w) minw = w;
4097         if (minh < w) minh = w;
4098      }
4099    if (minw < 5) minw = 5;
4100    if (minh < 5) minh = 5;
4101 
4102    if ((adx > minw) || (ady > minh))
4103      {
4104         it->dragging = EINA_TRUE;
4105         ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
4106         if (dy < 0)
4107           {
4108              if (ady > adx)
4109                evas_object_smart_callback_call
4110                  (WIDGET(it), "drag,start,up", eo_it);
4111              else
4112                {
4113                   if (dx < 0)
4114                     evas_object_smart_callback_call
4115                       (WIDGET(it), "drag,start,left", eo_it);
4116                   else
4117                     evas_object_smart_callback_call
4118                       (WIDGET(it), "drag,start,right", eo_it);
4119                }
4120           }
4121         else
4122           {
4123              if (ady > adx)
4124                evas_object_smart_callback_call
4125                  (WIDGET(it), "drag,start,down", eo_it);
4126              else
4127                {
4128                   if (dx < 0)
4129                     evas_object_smart_callback_call
4130                       (WIDGET(it), "drag,start,left", eo_it);
4131                   else
4132                     evas_object_smart_callback_call
4133                       (WIDGET(it), "drag,start,right", eo_it);
4134                }
4135           }
4136      }
4137 }
4138 
4139 static Eina_Bool
_long_press_cb(void * data)4140 _long_press_cb(void *data)
4141 {
4142    Elm_Gen_Item *it = data;
4143    Elm_Object_Item *eo_it_tmp;
4144    Eina_List *list;
4145    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4146 
4147    if (_is_no_select(it) ||
4148        elm_wdg_item_disabled_get(EO_OBJ(it)) || (it->dragging))
4149      goto end;
4150 
4151    sd->longpressed = EINA_TRUE;
4152    evas_object_smart_callback_call
4153          (WIDGET(it), "longpressed", EO_OBJ(it));
4154    if ((sd->reorder_mode) && !(it->item->type & ELM_GENLIST_ITEM_GROUP))
4155      {
4156         sd->reorder_it = it;
4157         sd->reorder_start_y = 0;
4158         if (it->deco_all_view)
4159           evas_object_stack_below(it->deco_all_view, sd->stack[1]);
4160         else
4161           evas_object_stack_below(VIEW(it), sd->stack[1]);
4162 
4163         elm_interface_scrollable_hold_set(sd->obj, EINA_TRUE);
4164         elm_interface_scrollable_bounce_allow_set
4165               (sd->obj, EINA_FALSE, EINA_FALSE);
4166 
4167         list = elm_genlist_realized_items_get
4168             ((sd)->obj);
4169         EINA_LIST_FREE(list, eo_it_tmp)
4170           {
4171              ELM_GENLIST_ITEM_DATA_GET(eo_it_tmp, it_tmp);
4172              if (it != it_tmp) _item_unselect(it_tmp);
4173           }
4174 
4175         if (elm_genlist_item_expanded_get(EO_OBJ(it)))
4176           {
4177              elm_genlist_item_expanded_set(EO_OBJ(it), EINA_FALSE);
4178              return ECORE_CALLBACK_RENEW;
4179           }
4180 
4181         if (!sd->decorate_all_mode)
4182           {
4183              edje_object_signal_emit(VIEW(it), SIGNAL_REORDER_ENABLED, "elm");
4184              if (_elm_config->atspi_mode)
4185                efl_access_state_changed_signal_emit(EO_OBJ(it), EFL_ACCESS_STATE_TYPE_ANIMATED, EINA_TRUE);
4186           }
4187      }
4188 
4189 end:
4190    it->long_timer = NULL;
4191    return ECORE_CALLBACK_CANCEL;
4192 }
4193 
4194 static void
_swipe_do(Elm_Gen_Item * it)4195 _swipe_do(Elm_Gen_Item *it)
4196 {
4197    int i, sum = 0;
4198    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4199 
4200    if (_is_no_select(it) ||
4201        elm_wdg_item_disabled_get(EO_OBJ(it))) return;
4202 
4203    sd->swipe = EINA_FALSE;
4204    for (i = 0; i < sd->movements; i++)
4205      {
4206         sum += sd->history[i].x;
4207         if (abs(sd->history[0].y - sd->history[i].y) > 10)
4208           return;
4209      }
4210 
4211    sum /= sd->movements;
4212    if (abs(sum - sd->history[0].x) <= 10) return;
4213    efl_event_callback_legacy_call
4214          (WIDGET(it), ELM_GENLIST_EVENT_SWIPE, EO_OBJ(it));
4215 }
4216 
4217 static Eina_Bool
_swipe_cancel(void * data)4218 _swipe_cancel(void *data)
4219 {
4220    Elm_Gen_Item *it = data;
4221    if (!it) return ECORE_CALLBACK_CANCEL;
4222    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4223 
4224    sd->swipe = EINA_FALSE;
4225    sd->movements = 0;
4226 
4227    return ECORE_CALLBACK_RENEW;
4228 }
4229 
4230 static Eina_Bool
_multi_cancel(void * data)4231 _multi_cancel(void *data)
4232 {
4233    ELM_GENLIST_DATA_GET(data, sd);
4234 
4235    if (!sd) return ECORE_CALLBACK_CANCEL;
4236    sd->multi_timeout = EINA_TRUE;
4237 
4238    return ECORE_CALLBACK_RENEW;
4239 }
4240 
4241 static void
_multi_touch_gesture_eval(Elm_Gen_Item * it)4242 _multi_touch_gesture_eval(Elm_Gen_Item *it)
4243 {
4244    Evas_Coord minw = 0, minh = 0;
4245    Evas_Coord off_x, off_y, off_mx, off_my;
4246    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4247    Elm_Object_Item *eo_it = EO_OBJ(it);
4248 
4249    sd->multi_touched = EINA_FALSE;
4250    ELM_SAFE_FREE(sd->multi_timer, ecore_timer_del);
4251    if (sd->multi_timeout)
4252      {
4253         sd->multi_timeout = EINA_FALSE;
4254         return;
4255      }
4256 
4257    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
4258    off_x = abs(sd->cur_x - sd->prev_x);
4259    off_y = abs(sd->cur_y - sd->prev_y);
4260    off_mx = abs(sd->cur_mx - sd->prev_mx);
4261    off_my = abs(sd->cur_my - sd->prev_my);
4262 
4263    if (((off_x > minw) || (off_y > minh)) && ((off_mx > minw)
4264                                               || (off_my > minh)))
4265      {
4266         if ((off_x + off_mx) > (off_y + off_my))
4267           {
4268              if ((sd->cur_x > sd->prev_x) && (sd->cur_mx > sd->prev_mx))
4269                efl_event_callback_legacy_call
4270                      (WIDGET(it), ELM_GENLIST_EVENT_MULTI_SWIPE_RIGHT, eo_it);
4271              else if ((sd->cur_x < sd->prev_x) && (sd->cur_mx < sd->prev_mx))
4272                efl_event_callback_legacy_call
4273                      (WIDGET(it), ELM_GENLIST_EVENT_MULTI_SWIPE_LEFT, eo_it);
4274              else if (abs(sd->cur_x - sd->cur_mx) >
4275                       abs(sd->prev_x - sd->prev_mx))
4276                efl_event_callback_legacy_call
4277                      (WIDGET(it), ELM_GENLIST_EVENT_MULTI_PINCH_OUT, eo_it);
4278              else
4279                efl_event_callback_legacy_call
4280                      (WIDGET(it), ELM_GENLIST_EVENT_MULTI_PINCH_IN, eo_it);
4281           }
4282         else
4283           {
4284              if ((sd->cur_y > sd->prev_y) && (sd->cur_my > sd->prev_my))
4285                efl_event_callback_legacy_call
4286                      (WIDGET(it), ELM_GENLIST_EVENT_MULTI_SWIPE_DOWN, eo_it);
4287              else if ((sd->cur_y < sd->prev_y) && (sd->cur_my < sd->prev_my))
4288                efl_event_callback_legacy_call
4289                      (WIDGET(it), ELM_GENLIST_EVENT_MULTI_SWIPE_UP, eo_it);
4290              else if (abs(sd->cur_y - sd->cur_my) >
4291                       abs(sd->prev_y - sd->prev_my))
4292                efl_event_callback_legacy_call
4293                      (WIDGET(it), ELM_GENLIST_EVENT_MULTI_PINCH_OUT, eo_it);
4294              else
4295                efl_event_callback_legacy_call
4296                      (WIDGET(it), ELM_GENLIST_EVENT_MULTI_PINCH_IN, eo_it);
4297           }
4298      }
4299 
4300    sd->multi_timeout = EINA_FALSE;
4301 }
4302 
4303 static void
_item_multi_down_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)4304 _item_multi_down_cb(void *data,
4305                     Evas *evas EINA_UNUSED,
4306                     Evas_Object *obj EINA_UNUSED,
4307                     void *event_info)
4308 {
4309    Elm_Gen_Item *it = data;
4310    Evas_Event_Multi_Down *ev = event_info;
4311    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4312 
4313    if ((sd->multi_device != 0) || (sd->multi_touched)
4314        || (sd->multi_timeout))
4315      return;
4316 
4317    sd->multi_device = ev->device;
4318    sd->multi_down = EINA_TRUE;
4319    sd->multi_touched = EINA_TRUE;
4320    sd->prev_mx = ev->canvas.x;
4321    sd->prev_my = ev->canvas.y;
4322    if (!sd->wasselected) _item_unselect(it);
4323    sd->wasselected = EINA_FALSE;
4324    sd->longpressed = EINA_FALSE;
4325    ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
4326    if (it->dragging)
4327      {
4328         it->dragging = EINA_FALSE;
4329         evas_object_smart_callback_call
4330               (WIDGET(it), "drag,stop", EO_OBJ(it));
4331      }
4332    ELM_SAFE_FREE(it->item->swipe_timer, ecore_timer_del);
4333    if (sd->on_hold)
4334      {
4335         sd->swipe = EINA_FALSE;
4336         sd->movements = 0;
4337         sd->on_hold = EINA_FALSE;
4338      }
4339 }
4340 
4341 static void
_item_multi_up_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)4342 _item_multi_up_cb(void *data,
4343                   Evas *evas EINA_UNUSED,
4344                   Evas_Object *obj EINA_UNUSED,
4345                   void *event_info)
4346 {
4347    Elm_Gen_Item *it = data;
4348    Evas_Event_Multi_Up *ev = event_info;
4349    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4350 
4351    if (sd->multi_device != ev->device) return;
4352    sd->multi_device = 0;
4353    sd->multi_down = EINA_FALSE;
4354    if (sd->mouse_down) return;
4355    _multi_touch_gesture_eval(data);
4356 }
4357 
4358 static void
_item_multi_move_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)4359 _item_multi_move_cb(void *data,
4360                     Evas *evas EINA_UNUSED,
4361                     Evas_Object *obj EINA_UNUSED,
4362                     void *event_info)
4363 {
4364    Elm_Gen_Item *it = data;
4365    Evas_Event_Multi_Move *ev = event_info;
4366    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4367 
4368    if (sd->multi_device != ev->device) return;
4369    sd->cur_mx = ev->cur.canvas.x;
4370    sd->cur_my = ev->cur.canvas.y;
4371 }
4372 
4373 static void
_item_mouse_down_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj,void * event_info)4374 _item_mouse_down_cb(void *data,
4375                     Evas *evas EINA_UNUSED,
4376                     Evas_Object *obj,
4377                     void *event_info)
4378 {
4379    Evas_Event_Mouse_Down *ev = event_info;
4380    Elm_Gen_Item *it = data;
4381    Evas_Coord x, y;
4382    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4383    Elm_Object_Item *eo_it = EO_OBJ(it);
4384 
4385    if (ev->button == 3)
4386      {
4387         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
4388         it->dx = ev->canvas.x - x;
4389         it->dy = ev->canvas.y - y;
4390         return;
4391      }
4392    if (ev->button != 1) return;
4393    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
4394      {
4395         sd->on_hold = EINA_TRUE;
4396      }
4397 
4398    it->down = EINA_TRUE;
4399    it->dragging = EINA_FALSE;
4400    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
4401    it->dx = ev->canvas.x - x;
4402    it->dy = ev->canvas.y - y;
4403    sd->mouse_down = EINA_TRUE;
4404    if (!sd->multi_touched)
4405      {
4406         sd->prev_x = ev->canvas.x;
4407         sd->prev_y = ev->canvas.y;
4408         sd->multi_timeout = EINA_FALSE;
4409         ecore_timer_del(sd->multi_timer);
4410         sd->multi_timer = ecore_timer_add(MULTI_DOWN_TIME, _multi_cancel, sd->obj);
4411      }
4412    sd->longpressed = EINA_FALSE;
4413    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) sd->on_hold = EINA_TRUE;
4414    else sd->on_hold = EINA_FALSE;
4415    if (sd->on_hold) return;
4416    sd->wasselected = it->selected;
4417 
4418    ecore_timer_del(it->item->swipe_timer);
4419    it->item->swipe_timer = ecore_timer_add(SWIPE_TIME, _swipe_cancel, it);
4420    ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
4421    if (it->realized)
4422      it->long_timer = ecore_timer_add
4423          (sd->longpress_timeout, _long_press_cb, it);
4424    else
4425      it->long_timer = NULL;
4426    sd->swipe = EINA_FALSE;
4427    sd->movements = 0;
4428    it->base->still_in = EINA_TRUE;
4429 
4430    if (_is_no_select(it) ||
4431         elm_wdg_item_disabled_get((Eo *)eo_it))
4432      return;
4433 
4434    // and finally call the user callbacks.
4435    // NOTE: keep this code at the bottom, as the user can change the
4436    //       list at this point (clear, delete, etc...)
4437    _item_highlight(it);
4438    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
4439      {
4440         evas_object_smart_callback_call
4441               ( WIDGET(it), "clicked,double", eo_it);
4442         efl_event_callback_legacy_call
4443               (WIDGET(it), ELM_GENLIST_EVENT_ACTIVATED, eo_it);
4444      }
4445    evas_object_smart_callback_call
4446          (WIDGET(it), "pressed", eo_it);
4447 }
4448 
4449 static Item_Block *
_item_block_new(Elm_Genlist_Data * sd,Eina_Bool prepend)4450 _item_block_new(Elm_Genlist_Data *sd,
4451                 Eina_Bool prepend)
4452 {
4453    Item_Block *itb;
4454 
4455    itb = calloc(1, sizeof(Item_Block));
4456    if (!itb) return NULL;
4457    itb->sd = sd;
4458    if (prepend)
4459      {
4460         sd->blocks = eina_inlist_prepend(sd->blocks, EINA_INLIST_GET(itb));
4461         _item_block_position_update(sd->blocks, 0);
4462      }
4463    else
4464      {
4465         sd->blocks = eina_inlist_append(sd->blocks, EINA_INLIST_GET(itb));
4466         itb->position_update = EINA_TRUE;
4467         if (sd->blocks != EINA_INLIST_GET(itb))
4468           {
4469              itb->position =
4470                ((Item_Block *)(EINA_INLIST_GET(itb)->prev))->position + 1;
4471           }
4472         else
4473           {
4474              itb->position = 0;
4475           }
4476      }
4477 
4478    return itb;
4479 }
4480 
4481 static void
_update_block_registration(Item_Block * itb,Elm_Gen_Item * element)4482 _update_block_registration(Item_Block *itb, Elm_Gen_Item *element)
4483 {
4484    Elm_Gen_Item *it = NULL;
4485    Eina_List *order = NULL;
4486    const Eina_List *l;
4487 
4488    if (!itb->realized) return;
4489 
4490    efl_ui_focus_manager_calc_register_logical(itb->sd->obj, EO_OBJ(element), itb->adapter, NULL);
4491 
4492    EINA_LIST_FOREACH(itb->items, l, it)
4493      {
4494         order = eina_list_append(order, EO_OBJ(it));
4495      }
4496 
4497    efl_ui_focus_manager_calc_update_order(itb->sd->obj, itb->adapter, order);
4498 }
4499 
4500 /**
4501  * @internal
4502  *
4503  * This function adds an item to a block's item list. This may or may not
4504  * rearrange existing blocks and create a new block.
4505  *
4506  */
4507 static Eina_Bool
_item_block_add(Elm_Genlist_Data * sd,Elm_Gen_Item * it)4508 _item_block_add(Elm_Genlist_Data *sd,
4509                 Elm_Gen_Item *it)
4510 {
4511    Item_Block *itb = NULL;
4512 
4513    // when a new item does not depend on another item
4514    if (!it->item->rel)
4515      {
4516 newblock:
4517         if (it->item->rel)
4518           {
4519              // FIXME: Why is this case here??? This doesn't make sense at all!
4520              // There shouldn't be a goto in the first place!
4521              itb = calloc(1, sizeof(Item_Block));
4522              if (!itb) return EINA_FALSE;
4523              itb->sd = sd;
4524              if (!it->item->rel->item->block)
4525                {
4526                   sd->blocks =
4527                     eina_inlist_append(sd->blocks, EINA_INLIST_GET(itb));
4528                   itb->items = eina_list_append(itb->items, it);
4529                   _update_block_registration(itb, it);
4530                   itb->position_update = EINA_TRUE;
4531                   it->position = eina_list_count(itb->items);
4532                   it->position_update = EINA_TRUE;
4533 
4534                   if (sd->blocks != EINA_INLIST_GET(itb))
4535                     {
4536                        itb->position =
4537                          ((Item_Block *)
4538                           (EINA_INLIST_GET(itb)->prev))->position + 1;
4539                     }
4540                   else
4541                     {
4542                        itb->position = 0;
4543                     }
4544                }
4545              else
4546                {
4547                   Eina_List *tmp;
4548 
4549                   tmp = eina_list_data_find_list(itb->items, it->item->rel);
4550                   if (it->item->before)
4551                     {
4552                        sd->blocks = eina_inlist_prepend_relative
4553                            (sd->blocks, EINA_INLIST_GET(itb),
4554                            EINA_INLIST_GET(it->item->rel->item->block));
4555                        itb->items =
4556                          eina_list_prepend_relative_list(itb->items, it, tmp);
4557 
4558                        /* Update index from where we prepended */
4559                        _item_position_update
4560                          (eina_list_prev(tmp), it->item->rel->position);
4561                        _item_block_position_update
4562                          (EINA_INLIST_GET(itb),
4563                          it->item->rel->item->block->position);
4564                     }
4565                   else
4566                     {
4567                        sd->blocks = eina_inlist_append_relative
4568                            (sd->blocks, EINA_INLIST_GET(itb),
4569                            EINA_INLIST_GET(it->item->rel->item->block));
4570                        itb->items =
4571                          eina_list_append_relative_list(itb->items, it, tmp);
4572 
4573                        /* Update block index from where we appended */
4574                        _item_position_update
4575                          (eina_list_next(tmp), it->item->rel->position + 1);
4576                        _item_block_position_update
4577                          (EINA_INLIST_GET(itb),
4578                          it->item->rel->item->block->position + 1);
4579                     }
4580                }
4581           }
4582         else
4583           {
4584              // item move_before, prepend, insert_before, sorted_insert with before
4585              if (it->item->before)
4586                {
4587                   if (sd->blocks)
4588                     {
4589                        itb = (Item_Block *)(sd->blocks);
4590                        if (itb->count >= sd->max_items_per_block)
4591                          {
4592                             itb = _item_block_new(sd, EINA_TRUE);
4593                             if (!itb) return EINA_FALSE;
4594                          }
4595                     }
4596                   else
4597                     {
4598                        itb = _item_block_new(sd, EINA_TRUE);
4599                        if (!itb) return EINA_FALSE;
4600                     }
4601                   itb->items = eina_list_prepend(itb->items, it);
4602                   _update_block_registration(itb, it);
4603                   _item_position_update(itb->items, 0);
4604                }
4605              // item move_after, append, insert_after, sorted_insert without before
4606              else
4607                {
4608                   if (sd->blocks)
4609                     {
4610                        itb = (Item_Block *)(sd->blocks->last);
4611                        if (itb->count >= sd->max_items_per_block)
4612                          {
4613                             itb = _item_block_new(sd, EINA_FALSE);
4614                             if (!itb) return EINA_FALSE;
4615                          }
4616                     }
4617                   else
4618                     {
4619                        itb = _item_block_new(sd, EINA_FALSE);
4620                        if (!itb) return EINA_FALSE;
4621                     }
4622                   itb->items = eina_list_append(itb->items, it);
4623                   _update_block_registration(itb, it);
4624                   it->position = eina_list_count(itb->items);
4625                }
4626           }
4627      }
4628    // when a new item depends on another item
4629    else
4630      {
4631         Eina_List *tmp;
4632 
4633         if (it->item->rel->item->queued)
4634           {
4635              /* NOTE: for a strange reason eina_list and eina_inlist
4636                 don't have the same property on sorted insertion
4637                 order, so the queue is not always ordered like the
4638                 item list.  This lead to issue where we depend on an
4639                 item that is not yet created. As a quick work around,
4640                 we reschedule the calc of the item and stop reordering
4641                 the list to prevent any nasty issue to show up here.
4642               */
4643              sd->queue = eina_list_append(sd->queue, it);
4644              sd->requeued = EINA_TRUE;
4645              it->item->queued = EINA_TRUE;
4646 
4647              return EINA_FALSE;
4648           }
4649         itb = it->item->rel->item->block;
4650         if (!itb) goto newblock;
4651         tmp = eina_list_data_find_list(itb->items, it->item->rel);
4652         if (it->item->before)
4653           {
4654              itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
4655              _update_block_registration(itb, it);
4656              _item_position_update
4657                (eina_list_prev(tmp), it->item->rel->position);
4658           }
4659         else
4660           {
4661              itb->items = eina_list_append_relative_list(itb->items, it, tmp);
4662              _update_block_registration(itb, it);
4663              _item_position_update
4664                (eina_list_next(tmp), it->item->rel->position + 1);
4665           }
4666      }
4667 
4668    itb->count++;
4669    itb->changed = EINA_TRUE;
4670    it->item->block = itb;
4671    efl_canvas_group_change(itb->sd->obj);
4672 
4673    if (itb->count > itb->sd->max_items_per_block)
4674      {
4675         int newc;
4676         Item_Block *itb2;
4677         Elm_Gen_Item *it2;
4678         Eina_Bool done = EINA_FALSE;
4679 
4680         newc = itb->count / 2;
4681 
4682         if (EINA_INLIST_GET(itb)->prev)
4683           {
4684              Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
4685 
4686              if (itbp->count + newc < sd->max_items_per_block / 2)
4687                {
4688                   /* moving items to previous block */
4689                   while ((itb->count > newc) && (itb->items))
4690                     {
4691                        it2 = eina_list_data_get(itb->items);
4692                        itb->items = eina_list_remove_list
4693                            (itb->items, itb->items);
4694                        itb->count--;
4695                        efl_ui_focus_manager_calc_unregister(itb->sd->obj, EO_OBJ(it2));
4696 
4697                        itbp->items = eina_list_append(itbp->items, it2);
4698                        _update_block_registration(itbp, it2);
4699                        it2->item->block = itbp;
4700                        itbp->count++;
4701                        if (!it2->hide)
4702                          {
4703                             itb->vis_count--;
4704                             itbp->num--;
4705                             itbp->vis_count++;
4706                          }
4707 
4708                        if (it2->realized)
4709                          {
4710                             _item_block_realize(itbp);
4711                          }
4712                     }
4713 
4714                   done = EINA_TRUE;
4715                }
4716           }
4717 
4718         if (!done && EINA_INLIST_GET(itb)->next)
4719           {
4720              Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
4721 
4722              if (itbn->count + newc < sd->max_items_per_block / 2)
4723                {
4724                   /* moving items to next block */
4725                   while ((itb->count > newc) && (itb->items))
4726                     {
4727                        Eina_List *l;
4728 
4729                        l = eina_list_last(itb->items);
4730                        it2 = eina_list_data_get(l);
4731                        itb->items = eina_list_remove_list(itb->items, l);
4732                        itb->count--;
4733                        efl_ui_focus_manager_calc_unregister(itb->sd->obj, EO_OBJ(it2));
4734 
4735                        itbn->items = eina_list_prepend(itbn->items, it2);
4736                        _update_block_registration(itbn, it2);
4737                        it2->item->block = itbn;
4738                        itbn->count++;
4739                        if (!it2->hide)
4740                          {
4741                             itb->h -= it->item->h;
4742                             itb->vis_count--;
4743                             itbn->h += it->item->h;
4744                             itbn->vis_count++;
4745                          }
4746 
4747                        if (it2->realized)
4748                          {
4749                             _item_block_realize(itbn);
4750                          }
4751                     }
4752 
4753                   done = EINA_TRUE;
4754                }
4755           }
4756 
4757         if (!done)
4758           {
4759              /* moving items to new block */
4760              itb2 = calloc(1, sizeof(Item_Block));
4761              if (!itb2) return EINA_FALSE;
4762              itb2->sd = sd;
4763              sd->blocks =
4764                eina_inlist_append_relative(sd->blocks, EINA_INLIST_GET(itb2),
4765                                            EINA_INLIST_GET(itb));
4766              itb2->changed = EINA_TRUE;
4767              while ((itb->count > newc) && (itb->items))
4768                {
4769                   Eina_List *l;
4770 
4771                   l = eina_list_last(itb->items);
4772                   it2 = l->data;
4773                   itb->items = eina_list_remove_list(itb->items, l);
4774                   itb->count--;
4775                   efl_ui_focus_manager_calc_unregister(itb->sd->obj, EO_OBJ(it2));
4776 
4777                   itb2->items = eina_list_prepend(itb2->items, it2);
4778                   _update_block_registration(itb2, it2);
4779                   it2->item->block = itb2;
4780                   itb2->count++;
4781                   if (!it2->hide)
4782                     {
4783                        itb->vis_count--;
4784                        itb->h -= it2->item->h;
4785                        itb2->vis_count++;
4786                        itb2->h += it2->item->h;
4787                     }
4788 
4789                   if (it2->realized)
4790                     {
4791                        _item_block_realize(itb2);
4792                     }
4793                }
4794 
4795              itb2->num = itb->num + itb->vis_count;
4796              itb2->x = itb->x;
4797              itb2->w = itb->w;
4798              itb2->y = itb->y + itb->h;
4799           }
4800      }
4801 
4802    return EINA_TRUE;
4803 }
4804 
4805 static Eina_Bool
_item_process(Elm_Genlist_Data * sd,Elm_Gen_Item * it)4806 _item_process(Elm_Genlist_Data *sd,
4807               Elm_Gen_Item *it)
4808 {
4809    if (!_item_block_add(sd, it)) return EINA_FALSE;
4810    if (!sd->blocks)
4811      _item_block_realize(it->item->block);
4812 
4813    return EINA_TRUE;
4814 }
4815 
4816 static void
_item_process_post(Elm_Genlist_Data * sd,Elm_Gen_Item * it)4817 _item_process_post(Elm_Genlist_Data *sd, Elm_Gen_Item *it)
4818 {
4819    Eina_Bool show_me = EINA_FALSE;
4820 
4821    EINA_SAFETY_ON_FALSE_RETURN(it && it->item && it->item->block);
4822    if (it->item->block->changed)
4823      {
4824         show_me = _item_block_recalc
4825             (it->item->block, it->item->block->num, EINA_TRUE);
4826         it->item->block->changed = 0;
4827         if (sd->pan_changed)
4828           {
4829              evas_object_smart_changed(sd->pan_obj);
4830           }
4831      }
4832    if (show_me) it->item->block->show_me = EINA_TRUE;
4833 
4834    /* when prepending, move the scroller along with the first selected
4835     * item to create the illusion that we're watching the selected
4836     * item this prevents the selected item being scrolled off the
4837     * viewport
4838     */
4839    if (sd->selected && it->item->before && !it->hide)
4840      {
4841         int y = 0, h;
4842         Elm_Object_Item *eo_it2;
4843 
4844         eo_it2 = sd->selected->data;
4845         ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
4846         if (!it2->item->block) return;
4847         if (it2->item->order_num_in < it->item->order_num_in) return;
4848         elm_interface_scrollable_content_pos_get(sd->obj, NULL, &y);
4849         evas_object_geometry_get(sd->pan_obj, NULL, NULL, NULL, &h);
4850         if ((it->y + it->item->block->y > y + h) ||
4851             (it->y + it->item->block->y + it->item->h < y))
4852           /* offscreen, just update */
4853            elm_interface_scrollable_content_region_show
4854             (sd->obj, it2->x + it2->item->block->x, y, it2->item->block->w, h);
4855         else
4856            elm_interface_scrollable_content_region_show
4857             (sd->obj, it->x + it->item->block->x, y + it->item->h, it->item->block->w, h);
4858      }
4859 }
4860 
4861 static int
_queue_process(Elm_Genlist_Data * sd)4862 _queue_process(Elm_Genlist_Data *sd)
4863 {
4864    int n;
4865    double t0, t;
4866    Evas *e = evas_object_evas_get(sd->obj);
4867 
4868    t0 = ecore_time_get();
4869    evas_event_freeze(e);
4870    for (n = 0; (sd->queue) && (n < ITEM_QUEUE_MAX); n++)
4871      {
4872         Elm_Gen_Item *it;
4873 
4874         it = eina_list_data_get(sd->queue);
4875         sd->queue = eina_list_remove_list(sd->queue, sd->queue);
4876         it->item->queued = EINA_FALSE;
4877         if (!_item_process(sd, it)) continue;
4878         t = ecore_time_get();
4879         _item_process_post(sd, it);
4880         /* same as eina_inlist_count > 1 */
4881         if (sd->blocks && sd->blocks->next)
4882           {
4883              if ((t - t0) > (ecore_animator_frametime_get())) break;
4884           }
4885      }
4886    evas_event_thaw(e);
4887    evas_event_thaw_eval(e);
4888    return n;
4889 }
4890 
4891 static Eina_Bool
_idle_process(void * data,Eina_Bool * wakeup)4892 _idle_process(void *data,
4893               Eina_Bool *wakeup)
4894 {
4895    Elm_Genlist_Data *sd = data;
4896 
4897    if (_queue_process(sd) > 0) *wakeup = EINA_TRUE;
4898    if (!sd->queue)
4899      {
4900         return ECORE_CALLBACK_CANCEL;
4901      }
4902    return ECORE_CALLBACK_RENEW;
4903 }
4904 
4905 static Eina_Bool
_item_idle_enterer(void * data)4906 _item_idle_enterer(void *data)
4907 {
4908    Eina_Bool wakeup = EINA_FALSE;
4909    ELM_GENLIST_DATA_GET(data, sd);
4910    Eina_Bool ok = _idle_process(sd, &wakeup);
4911 
4912    if (wakeup)
4913      {
4914         // wake up mainloop
4915         efl_canvas_group_change(sd->obj);
4916      }
4917    if (ok == ECORE_CALLBACK_CANCEL) sd->queue_idle_enterer = NULL;
4918 
4919    return ok;
4920 }
4921 
4922 static void
_requeue_idle_enterer(Elm_Genlist_Data * sd)4923 _requeue_idle_enterer(Elm_Genlist_Data *sd)
4924 {
4925    ecore_idle_enterer_del(sd->queue_idle_enterer);
4926    sd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, sd->obj);
4927 }
4928 
4929 static void
_item_queue(Elm_Genlist_Data * sd,Elm_Gen_Item * it,Eina_Compare_Cb cb)4930 _item_queue(Elm_Genlist_Data *sd,
4931             Elm_Gen_Item *it,
4932             Eina_Compare_Cb cb)
4933 {
4934    Evas_Coord w = 0;
4935 
4936    if (it->item->queued) return;
4937    it->item->queued = EINA_TRUE;
4938    if (cb && !sd->requeued)
4939      sd->queue = eina_list_sorted_insert(sd->queue, cb, it);
4940    else
4941      sd->queue = eina_list_append(sd->queue, it);
4942 // FIXME: why does a freeze then thaw here cause some genlist
4943 // elm_genlist_item_append() to be much much slower?
4944 //   evas_event_freeze(evas_object_evas_get(sd->obj));
4945    while ((sd->queue) && ((!sd->blocks) || (!sd->blocks->next)))
4946      {
4947         ELM_SAFE_FREE(sd->queue_idle_enterer, ecore_idle_enterer_del);
4948         _queue_process(sd);
4949      }
4950    while ((sd->queue) && (sd->blocks) &&
4951           (sd->homogeneous) && (sd->mode == ELM_LIST_COMPRESS))
4952      {
4953         ELM_SAFE_FREE(sd->queue_idle_enterer, ecore_idle_enterer_del);
4954         _queue_process(sd);
4955      }
4956 
4957 //   evas_event_thaw(evas_object_evas_get(sd->obj));
4958 //   evas_event_thaw_eval(evas_object_evas_get(sd->obj));
4959    evas_object_geometry_get(sd->obj, NULL, NULL, &w, NULL);
4960    if (w > 0) _requeue_idle_enterer(sd);
4961 
4962    if (_elm_config->atspi_mode)
4963      {
4964         efl_access_added(EO_OBJ(it));
4965         efl_access_children_changed_added_signal_emit(sd->obj, EO_OBJ(it));
4966      }
4967 }
4968 
4969 /* If the application wants to know the relative item, use
4970  * elm_genlist_item_prev_get(it)*/
4971 static void
_item_move_after(Elm_Gen_Item * it,Elm_Gen_Item * after)4972 _item_move_after(Elm_Gen_Item *it,
4973                  Elm_Gen_Item *after)
4974 {
4975    if (!it) return;
4976    if (!after) return;
4977    if (it == after) return;
4978    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
4979 
4980    sd->items =
4981      eina_inlist_remove(sd->items, EINA_INLIST_GET(it));
4982    if (it->item->block) _item_block_del(it);
4983 
4984    sd->items = eina_inlist_append_relative
4985        (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
4986    if (it->item->rel)
4987       it->item->rel->item->rel_revs =
4988          eina_list_remove(it->item->rel->item->rel_revs, it);
4989    it->item->rel = after;
4990    after->item->rel_revs = eina_list_append(after->item->rel_revs, it);
4991    it->item->before = EINA_FALSE;
4992    if (after->item->group_item) it->item->group_item = after->item->group_item;
4993    _item_queue(sd, it, NULL);
4994 
4995    efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_MOVED_AFTER, EO_OBJ(it));
4996 }
4997 
4998 static void
_access_activate_cb(void * data EINA_UNUSED,Evas_Object * part_obj EINA_UNUSED,Elm_Object_Item * eo_it)4999 _access_activate_cb(void *data EINA_UNUSED,
5000                     Evas_Object *part_obj EINA_UNUSED,
5001                     Elm_Object_Item *eo_it)
5002 {
5003    ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
5004    if (!it) return;
5005 
5006    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
5007    if (!sd) return;
5008 
5009    if (sd->multi)
5010      {
5011         if (!it->selected)
5012           {
5013              _item_highlight(it);
5014              _item_select(it);
5015           }
5016         else
5017           _item_unselect(it);
5018      }
5019    else
5020      {
5021         if (!it->selected)
5022           {
5023              while (sd->selected)
5024                {
5025                   Elm_Object_Item *eo_sel = sd->selected->data;
5026                   Elm_Gen_Item *sel = efl_data_scope_get(eo_sel, ELM_GENLIST_ITEM_CLASS);
5027                   _item_unselect(sel);
5028                }
5029           }
5030         else
5031           {
5032              const Eina_List *l, *l_next;
5033              Elm_Object_Item *eo_it2;
5034 
5035              EINA_LIST_FOREACH_SAFE(sd->selected, l, l_next, eo_it2)
5036                {
5037                   ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
5038                   if (it2 != it)
5039                     _item_unselect(it2);
5040                }
5041           }
5042         _item_highlight(it);
5043         _item_select(it);
5044      }
5045 }
5046 
5047 /* If the application wants to know the relative item, use
5048  * elm_genlist_item_next_get(it)*/
5049 static void
_item_move_before(Elm_Gen_Item * it,Elm_Gen_Item * before)5050 _item_move_before(Elm_Gen_Item *it,
5051                   Elm_Gen_Item *before)
5052 {
5053    if (!it) return;
5054    if (!before) return;
5055    if (it == before) return;
5056    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
5057 
5058    sd->items =
5059      eina_inlist_remove(sd->items, EINA_INLIST_GET(it));
5060    if (it->item->block) _item_block_del(it);
5061    sd->items = eina_inlist_prepend_relative
5062        (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
5063    if (it->item->rel)
5064       it->item->rel->item->rel_revs =
5065          eina_list_remove(it->item->rel->item->rel_revs, it);
5066    it->item->rel = before;
5067    before->item->rel_revs = eina_list_append(before->item->rel_revs, it);
5068    it->item->before = EINA_TRUE;
5069    if (before->item->group_item)
5070      it->item->group_item = before->item->group_item;
5071    _item_queue(sd, it, NULL);
5072 
5073    efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_MOVED_BEFORE, EO_OBJ(it));
5074 }
5075 
5076 static void
_item_mouse_up_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)5077 _item_mouse_up_cb(void *data,
5078                   Evas *evas EINA_UNUSED,
5079                   Evas_Object *obj EINA_UNUSED,
5080                   void *event_info)
5081 {
5082    Evas_Event_Mouse_Up *ev = event_info;
5083    Eina_Bool dragged = EINA_FALSE;
5084    Elm_Gen_Item *it = data;
5085    Evas_Coord x, y, dx, dy;
5086 
5087    if ((ev->button == 3) && (!it->dragging))
5088      {
5089         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
5090         dx = it->dx - (ev->canvas.x - x);
5091         dy = it->dy - (ev->canvas.y - y);
5092         if (dx < 0) dx = -dx;
5093         if (dy < 0) dy = -dy;
5094         if ((dx < 5) && (dy < 5))
5095           evas_object_smart_callback_call
5096                 ( WIDGET(it), "clicked,right", EO_OBJ(it));
5097         return;
5098      }
5099 
5100    if (ev->button != 1) return;
5101    it->down = EINA_FALSE;
5102    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
5103 
5104    evas_object_ref(WIDGET(it));
5105    efl_ref(EO_OBJ(it));
5106    sd->mouse_down = EINA_FALSE;
5107 
5108    efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_RELEASED, EO_OBJ(it));
5109 
5110    if (sd->multi_touched)
5111      {
5112         if ((!sd->multi) && (!it->selected) && (it->highlighted))
5113           _item_unhighlight(it);
5114         if (sd->multi_down) goto early;
5115         _multi_touch_gesture_eval(it);
5116         goto early;
5117      }
5118    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
5119      sd->on_hold = EINA_TRUE;
5120    else sd->on_hold = EINA_FALSE;
5121    ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
5122    if (it->dragging)
5123      {
5124         it->dragging = EINA_FALSE;
5125         evas_object_smart_callback_call
5126               (WIDGET(it), "drag,stop", EO_OBJ(it));
5127         dragged = 1;
5128      }
5129    ELM_SAFE_FREE(it->item->swipe_timer, ecore_timer_del);
5130    if (sd->multi_timer)
5131      {
5132         ELM_SAFE_FREE(sd->multi_timer, ecore_timer_del);
5133         sd->multi_timeout = EINA_FALSE;
5134      }
5135    if (sd->swipe)
5136      {
5137         if (!sd->wasselected) _item_unselect(it);
5138         _swipe_do(it);
5139         sd->longpressed = EINA_FALSE;
5140         sd->on_hold = EINA_FALSE;
5141         sd->wasselected = EINA_FALSE;
5142         goto early;
5143      }
5144    if ((sd->reorder_mode) && (sd->reorder_it))
5145      {
5146         Evas_Coord it_scrl_y = ev->canvas.y - sd->reorder_it->dy;
5147         sd->reorder_fast = 0;
5148 
5149         if (sd->reorder_rel &&
5150             (sd->reorder_it->parent == sd->reorder_rel->parent))
5151           {
5152              if (it_scrl_y <= sd->reorder_rel->item->scrl_y)
5153                _item_move_before(sd->reorder_it, sd->reorder_rel);
5154              else
5155                _item_move_after(sd->reorder_it, sd->reorder_rel);
5156              efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_MOVED, EO_OBJ(it));
5157           }
5158         else
5159           {
5160              efl_canvas_group_change(sd->obj);
5161           }
5162         edje_object_signal_emit(VIEW(it), SIGNAL_REORDER_DISABLED, "elm");
5163         if (_elm_config->atspi_mode)
5164           efl_access_state_changed_signal_emit(EO_OBJ(it), EFL_ACCESS_STATE_TYPE_ANIMATED, EINA_FALSE);
5165         sd->reorder_it = sd->reorder_rel = NULL;
5166         elm_interface_scrollable_hold_set(sd->obj, EINA_FALSE);
5167         elm_interface_scrollable_bounce_allow_set
5168               (sd->obj, sd->h_bounce, sd->v_bounce);
5169      }
5170    if (sd->longpressed)
5171      {
5172         if (!sd->wasselected) _item_unselect(it);
5173         sd->longpressed = EINA_FALSE;
5174         sd->wasselected = EINA_FALSE;
5175         goto early;
5176      }
5177    if (dragged)
5178      {
5179         if (it->want_unrealize)
5180           {
5181              _elm_genlist_item_unrealize(it, EINA_FALSE);
5182              if (it->item->block->want_unrealize)
5183                _item_block_unrealize(it->item->block);
5184           }
5185      }
5186 
5187    /* this is handled implicitly in _item_unselect() below unless there
5188     * will be no select
5189     */
5190    if (!it->selected && it->highlighted && _is_no_select(it))
5191      _item_unhighlight(it);
5192 
5193    if ((ev->flags != EVAS_BUTTON_NONE) ||
5194        (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) ||
5195        !it->base->still_in ||
5196        _is_no_select(it) ||
5197        (elm_wdg_item_disabled_get(EO_OBJ(it))))
5198      goto early;
5199 
5200    evas_object_ref(sd->obj);
5201 
5202    if (sd->focused_item != EO_OBJ(it))
5203      elm_object_item_focus_set(EO_OBJ(it), EINA_TRUE);
5204 
5205    if (efl_invalidated_get(EO_OBJ(it))) goto deleted;
5206 
5207    if (sd->multi &&
5208        ((sd->multi_select_mode != ELM_OBJECT_MULTI_SELECT_MODE_WITH_CONTROL) ||
5209         (evas_key_modifier_is_set(ev->modifiers, "Control"))))
5210      {
5211         if (!it->selected)
5212           {
5213              /* this should only be handled on mouse down
5214              _item_highlight(it);
5215              */
5216              if (_item_select(it)) goto deleted;
5217           }
5218         else
5219          _item_unselect(it);
5220      }
5221    else
5222      {
5223         if (!it->selected)
5224           {
5225              while (sd->selected)
5226                {
5227                   Elm_Object_Item *eo_sel = sd->selected->data;
5228                   Elm_Gen_Item *sel = efl_data_scope_get(eo_sel, ELM_GENLIST_ITEM_CLASS);
5229                   _item_unselect(sel);
5230                }
5231           }
5232         else
5233           {
5234              const Eina_List *l, *l_next;
5235              Elm_Object_Item *eo_it2;
5236 
5237              EINA_LIST_FOREACH_SAFE(sd->selected, l, l_next, eo_it2)
5238                {
5239                   ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
5240                   if (it2 != it)
5241                     _item_unselect(it2);
5242                }
5243           }
5244         /* this should only be handled on mouse down
5245         _item_highlight(it);
5246         */
5247         if (_item_select(it)) goto deleted;
5248      }
5249 
5250  deleted:
5251    evas_object_unref(sd->obj);
5252  early:
5253    evas_object_unref(WIDGET(it));
5254    efl_unref(EO_OBJ(it));
5255 }
5256 
5257 static void
_item_mouse_callbacks_add(Elm_Gen_Item * it,Evas_Object * view)5258 _item_mouse_callbacks_add(Elm_Gen_Item *it,
5259                           Evas_Object *view)
5260 {
5261    if (it->callbacks) return ;
5262    it->callbacks = EINA_TRUE;
5263    evas_object_event_callback_add
5264      (view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
5265    evas_object_event_callback_add
5266      (view, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
5267    evas_object_event_callback_add
5268      (view, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb, it);
5269    evas_object_event_callback_add
5270      (view, EVAS_CALLBACK_MULTI_DOWN, _item_multi_down_cb, it);
5271    evas_object_event_callback_add
5272      (view, EVAS_CALLBACK_MULTI_UP, _item_multi_up_cb, it);
5273    evas_object_event_callback_add
5274      (view, EVAS_CALLBACK_MULTI_MOVE, _item_multi_move_cb, it);
5275    evas_object_event_callback_add
5276      (view, EVAS_CALLBACK_MOUSE_IN, _item_mouse_in_cb, it);
5277 }
5278 
5279 static void
_item_mouse_callbacks_del(Elm_Gen_Item * it,Evas_Object * view)5280 _item_mouse_callbacks_del(Elm_Gen_Item *it,
5281                           Evas_Object *view)
5282 {
5283    if (!it->callbacks) return ;
5284    it->callbacks = EINA_FALSE;
5285    evas_object_event_callback_del_full
5286      (view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
5287    evas_object_event_callback_del_full
5288      (view, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
5289    evas_object_event_callback_del_full
5290      (view, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb, it);
5291    evas_object_event_callback_del_full
5292      (view, EVAS_CALLBACK_MULTI_DOWN, _item_multi_down_cb, it);
5293    evas_object_event_callback_del_full
5294      (view, EVAS_CALLBACK_MULTI_UP, _item_multi_up_cb, it);
5295    evas_object_event_callback_del_full
5296      (view, EVAS_CALLBACK_MULTI_MOVE, _item_multi_move_cb, it);
5297    evas_object_event_callback_del_full
5298      (view, EVAS_CALLBACK_MOUSE_IN, _item_mouse_in_cb, it);
5299 }
5300 
5301 static Eina_Bool
_scroll_hold_timer_cb(void * data)5302 _scroll_hold_timer_cb(void *data)
5303 {
5304    ELM_GENLIST_DATA_GET(data, sd);
5305 
5306    if (!data) return ECORE_CALLBACK_CANCEL;
5307 
5308    elm_interface_scrollable_hold_set(sd->obj, EINA_FALSE);
5309    sd->scr_hold_timer = NULL;
5310 
5311    return ECORE_CALLBACK_CANCEL;
5312 }
5313 
5314 static void
_decorate_item_unrealize(Elm_Gen_Item * it,Eina_Bool state_update)5315 _decorate_item_unrealize(Elm_Gen_Item *it, Eina_Bool state_update)
5316 {
5317    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
5318    Evas_Object *obj = sd->obj;
5319    Evas *e;
5320 
5321    if (!it->item->deco_it_view) return;
5322 
5323    e = evas_object_evas_get(obj);
5324    evas_event_freeze(e);
5325 
5326    _view_clear(it->item->deco_it_view, &(it->item->deco_it_texts),
5327                &(it->item->deco_it_contents));
5328 
5329    edje_object_part_unswallow(it->item->deco_it_view, VIEW(it));
5330    ELM_SAFE_FREE(it->item->deco_it_view, evas_object_del);
5331    evas_object_smart_member_add(VIEW(it), sd->pan_obj);
5332    evas_object_clip_set(VIEW(it), evas_object_clip_get(sd->pan_obj));
5333    if (state_update)
5334      {
5335         _elm_genlist_item_state_update(it);
5336         _item_order_update(it, it->item->order_num_in, EINA_TRUE);
5337      }
5338 
5339    if (sd->mode_item != it)
5340      it->decorate_it_set = EINA_FALSE;
5341 
5342    evas_event_thaw(e);
5343    evas_event_thaw_eval(e);
5344 }
5345 
5346 static void
_decorate_item_finished_signal_cb(void * data,Evas_Object * obj,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)5347 _decorate_item_finished_signal_cb(void *data,
5348                                   Evas_Object *obj,
5349                                   const char *emission EINA_UNUSED,
5350                                   const char *source EINA_UNUSED)
5351 {
5352    Elm_Gen_Item *it = data;
5353    char buf[1024];
5354    Evas *te;
5355 
5356    if (!it || !obj) return;
5357    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
5358 
5359    te = evas_object_evas_get(obj);
5360 
5361    if ((!it->realized) || (!it->item->deco_it_view)) return;
5362 
5363    evas_event_freeze(te);
5364    snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished",
5365             sd->decorate_it_type);
5366    edje_object_signal_callback_del_full
5367      (it->item->deco_it_view, buf, "elm", _decorate_item_finished_signal_cb, it);
5368    it->item->nocache_once = EINA_FALSE;
5369    _decorate_item_unrealize(it, EINA_TRUE);
5370    if (it->item->group_item)
5371      evas_object_stack_above(it->item->VIEW(group_item), sd->stack[1]);
5372 
5373    evas_event_thaw(te);
5374    evas_event_thaw_eval(te);
5375 }
5376 
5377 static void
_item_unrealize(Elm_Gen_Item * it)5378 _item_unrealize(Elm_Gen_Item *it)
5379 {
5380    Evas_Object *c;
5381    Eina_List *cache = NULL;
5382 
5383    EINA_LIST_FREE(it->item->flip_contents, c)
5384      evas_object_del(c);
5385 
5386    /* access */
5387    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
5388      _elm_access_widget_item_unregister(it->base);
5389 
5390    // unswallow VIEW(it) first then manipulate VIEW(it)
5391    _decorate_item_unrealize(it, EINA_FALSE);
5392    if (it->item->wsd->decorate_all_mode) _decorate_all_item_unrealize(it);
5393 
5394    if (!_item_cache_add(it, _content_cache_add(it, &cache)))
5395      {
5396         Evas_Object *view = VIEW(it);
5397         efl_wref_del(VIEW(it), &VIEW(it));
5398         ELM_SAFE_FREE(view, efl_del);
5399         VIEW(it) = NULL;
5400         it->callbacks = EINA_FALSE;
5401         ELM_SAFE_FREE(it->spacer, evas_object_del);
5402         EINA_LIST_FREE(cache, c)
5403           {
5404              evas_object_del(c);
5405           }
5406      }
5407 
5408    it->states = NULL;
5409    it->realized = EINA_FALSE;
5410    it->want_unrealize = EINA_FALSE;
5411 }
5412 
5413 static void
_item_temp_realize(Elm_Gen_Item * it,const int index)5414 _item_temp_realize(Elm_Gen_Item *it, const int index)
5415 {
5416    it->item->unfocusable = EINA_TRUE;
5417    _item_realize(it, index, EINA_TRUE);
5418    _elm_genlist_item_unrealize(it, EINA_TRUE);
5419    it->item->unfocusable = EINA_FALSE;
5420 }
5421 
5422 static Eina_Bool
_item_block_recalc(Item_Block * itb,const int blk_idx,Eina_Bool qadd)5423 _item_block_recalc(Item_Block *itb, const int blk_idx, Eina_Bool qadd)
5424 {
5425    const Eina_List *l;
5426    Elm_Gen_Item *it;
5427    Evas_Coord minw = 0, minh = 0;
5428    Eina_Bool show_me = EINA_FALSE, changed = EINA_FALSE;
5429    Evas_Coord y = 0;
5430    Item_Size *size = NULL;
5431    int vis_count = 0;
5432 
5433    itb->num = blk_idx;
5434    EINA_LIST_FOREACH(itb->items, l, it)
5435      {
5436         show_me |= it->item->show_me;
5437 
5438         if (!_item_filtered_get(it, itb->sd))
5439           {
5440              if (it->realized) evas_object_hide(VIEW(it));
5441              continue;
5442           }
5443         if (!itb->realized)
5444           {
5445              if (itb->sd->homogeneous &&
5446                  ((!size) || it->itc != size->itc))
5447                size = eina_hash_find(itb->sd->size_caches, &(it->itc));
5448              if (qadd || (itb->sd->homogeneous && !size))
5449                {
5450                   if (!it->item->mincalcd) changed = EINA_TRUE;
5451                   if (changed)
5452                     {
5453                        if (!size || (it->item->expanded_depth != size->expanded_depth))
5454                          {
5455                             _item_temp_realize(it, blk_idx + vis_count);
5456                          }
5457                        else
5458                          {
5459                             it->item->w = it->item->minw = size->minw;
5460                             it->item->h = it->item->minh = size->minh;
5461                             it->item->mincalcd = EINA_TRUE;
5462                          }
5463                     }
5464                }
5465              else
5466                {
5467                   if ((itb->sd->homogeneous) && size &&
5468                       (it->item->expanded_depth == size->expanded_depth) &&
5469                       (itb->sd->mode == ELM_LIST_COMPRESS))
5470                     {
5471                        it->item->w = it->item->minw = size->minw;
5472                        it->item->h = it->item->minh = size->minh;
5473                        it->item->mincalcd = EINA_TRUE;
5474                     }
5475                   else
5476                     _item_temp_realize(it, blk_idx + vis_count);
5477                }
5478           }
5479         else
5480           {
5481              if (!it->item->mincalcd) changed = EINA_TRUE;
5482              _item_realize(it, blk_idx + vis_count, EINA_FALSE);
5483           }
5484         minh += it->item->minh;
5485         if (minw < it->item->minw) minw = it->item->minw;
5486         vis_count++;
5487         it->x = 0;
5488         it->y = y;
5489         y += it->item->h;
5490      }
5491    if (changed) itb->sd->pan_changed = changed;
5492    itb->minw = minw;
5493    itb->minh = minh;
5494    itb->changed = EINA_FALSE;
5495    itb->position_update = EINA_FALSE;
5496    itb->vis_count = vis_count;
5497 
5498    return show_me;
5499 }
5500 
5501 static void
_update_job(void * data)5502 _update_job(void *data)
5503 {
5504    Eina_Bool position = EINA_FALSE, recalc = EINA_FALSE;
5505    ELM_GENLIST_DATA_GET(data, sd);
5506    Item_Block *itb;
5507    Eina_List *l2;
5508    int num, num0;
5509    Evas *e = evas_object_evas_get(sd->obj);;
5510 
5511    sd->update_job = NULL;
5512    num = 0;
5513 
5514    evas_event_freeze(e);
5515    EINA_INLIST_FOREACH(sd->blocks, itb)
5516      {
5517         Evas_Coord itminw, itminh;
5518         Elm_Gen_Item *it;
5519 
5520         if (!itb->updateme)
5521           {
5522              if (position)
5523                _item_block_position(itb, num);
5524              num += itb->vis_count;
5525              continue;
5526           }
5527         num0 = num;
5528         recalc = EINA_FALSE;
5529         EINA_LIST_FOREACH(itb->items, l2, it)
5530           {
5531              if (it->item->updateme)
5532                {
5533                   itminw = it->item->minw;
5534                   itminh = it->item->minh;
5535 
5536                   it->item->updateme = EINA_FALSE;
5537                   if (it->realized)
5538                     {
5539                        _elm_genlist_item_unrealize(it, EINA_FALSE);
5540                        _item_realize(it, num, EINA_FALSE);
5541                        position = EINA_TRUE;
5542                     }
5543                   else
5544                     {
5545                        _item_realize(it, num, EINA_TRUE);
5546                        _elm_genlist_item_unrealize(it, EINA_TRUE);
5547                     }
5548                   if ((it->item->minw != itminw) || (it->item->minh != itminh))
5549                     recalc = EINA_TRUE;
5550                }
5551              if (!it->hide) num++;
5552           }
5553         itb->updateme = EINA_FALSE;
5554         if (recalc)
5555           {
5556              position = EINA_TRUE;
5557              itb->changed = EINA_TRUE;
5558              _item_block_recalc(itb, num0, EINA_FALSE);
5559              _item_block_position(itb, num0);
5560           }
5561      }
5562    if (position)
5563      {
5564         efl_canvas_group_change(sd->pan_obj);
5565         efl_canvas_group_change(sd->obj);
5566      }
5567    evas_event_thaw(e);
5568    evas_event_thaw_eval(e);
5569 }
5570 
5571 static void
_scroll_animate_start_cb(Evas_Object * obj,void * data EINA_UNUSED)5572 _scroll_animate_start_cb(Evas_Object *obj,
5573                          void *data EINA_UNUSED)
5574 {
5575    evas_object_smart_callback_call(obj, "scroll,anim,start", NULL);
5576 }
5577 
5578 static void
_scroll_animate_stop_cb(Evas_Object * obj,void * data EINA_UNUSED)5579 _scroll_animate_stop_cb(Evas_Object *obj,
5580                         void *data EINA_UNUSED)
5581 {
5582    evas_object_smart_callback_call(obj, "scroll,anim,stop", NULL);
5583 }
5584 
5585 static void
_scroll_drag_start_cb(Evas_Object * obj,void * data EINA_UNUSED)5586 _scroll_drag_start_cb(Evas_Object *obj,
5587                       void *data EINA_UNUSED)
5588 {
5589    evas_object_smart_callback_call(obj, "scroll,drag,start", NULL);
5590 }
5591 
5592 static void
_scroll_cb(Evas_Object * obj,void * data EINA_UNUSED)5593 _scroll_cb(Evas_Object *obj,
5594            void *data EINA_UNUSED)
5595 {
5596    evas_object_smart_callback_call(obj, "scroll", NULL);
5597 }
5598 
5599 static void
_scroll_drag_stop_cb(Evas_Object * obj,void * data EINA_UNUSED)5600 _scroll_drag_stop_cb(Evas_Object *obj,
5601                      void *data EINA_UNUSED)
5602 {
5603    evas_object_smart_callback_call(obj, "scroll,drag,stop", NULL);
5604 }
5605 
5606 static void
_edge_left_cb(Evas_Object * obj,void * data EINA_UNUSED)5607 _edge_left_cb(Evas_Object *obj,
5608               void *data EINA_UNUSED)
5609 {
5610    efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_EDGE_LEFT, NULL);
5611 }
5612 
5613 static void
_edge_right_cb(Evas_Object * obj,void * data EINA_UNUSED)5614 _edge_right_cb(Evas_Object *obj,
5615                void *data EINA_UNUSED)
5616 {
5617    efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_EDGE_RIGHT, NULL);
5618 }
5619 
5620 static void
_edge_top_cb(Evas_Object * obj,void * data EINA_UNUSED)5621 _edge_top_cb(Evas_Object *obj,
5622              void *data EINA_UNUSED)
5623 {
5624    efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_EDGE_TOP, NULL);
5625 }
5626 
5627 static void
_edge_bottom_cb(Evas_Object * obj,void * data EINA_UNUSED)5628 _edge_bottom_cb(Evas_Object *obj,
5629                 void *data EINA_UNUSED)
5630 {
5631    efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_EDGE_BOTTOM, NULL);
5632 }
5633 
5634 static void
_vbar_drag_cb(Evas_Object * obj,void * data EINA_UNUSED)5635 _vbar_drag_cb(Evas_Object *obj,
5636                 void *data EINA_UNUSED)
5637 {
5638    efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_VBAR_DRAG, NULL);
5639 }
5640 
5641 static void
_vbar_press_cb(Evas_Object * obj,void * data EINA_UNUSED)5642 _vbar_press_cb(Evas_Object *obj,
5643                 void *data EINA_UNUSED)
5644 {
5645    efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_VBAR_PRESS, NULL);
5646 }
5647 
5648 static void
_vbar_unpress_cb(Evas_Object * obj,void * data EINA_UNUSED)5649 _vbar_unpress_cb(Evas_Object *obj,
5650                 void *data EINA_UNUSED)
5651 {
5652    efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_VBAR_UNPRESS, NULL);
5653 }
5654 
5655 static void
_hbar_drag_cb(Evas_Object * obj,void * data EINA_UNUSED)5656 _hbar_drag_cb(Evas_Object *obj,
5657                 void *data EINA_UNUSED)
5658 {
5659    efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_HBAR_DRAG, NULL);
5660 }
5661 
5662 static void
_hbar_press_cb(Evas_Object * obj,void * data EINA_UNUSED)5663 _hbar_press_cb(Evas_Object *obj,
5664                 void *data EINA_UNUSED)
5665 {
5666    efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_HBAR_PRESS, NULL);
5667 }
5668 
5669 static void
_hbar_unpress_cb(Evas_Object * obj,void * data EINA_UNUSED)5670 _hbar_unpress_cb(Evas_Object *obj,
5671                 void *data EINA_UNUSED)
5672 {
5673    efl_event_callback_legacy_call(obj, ELM_GENLIST_EVENT_HBAR_UNPRESS, NULL);
5674 }
5675 
5676 static void
_decorate_item_realize(Elm_Gen_Item * it)5677 _decorate_item_realize(Elm_Gen_Item *it)
5678 {
5679    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
5680    Evas_Object *obj = sd->obj;
5681    char buf[1024];
5682    Evas *e;
5683 
5684    if (it->item->deco_it_view) return;
5685 
5686    e = evas_object_evas_get(obj);
5687    evas_event_freeze(e);
5688    it->item->deco_it_view = _view_create(it, it->itc->decorate_item_style);
5689 
5690    /* signal callback add */
5691    evas_object_event_callback_add
5692      (it->item->deco_it_view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb,
5693      it);
5694    evas_object_event_callback_add
5695      (it->item->deco_it_view, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up_cb, it);
5696    evas_object_event_callback_add
5697      (it->item->deco_it_view, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move_cb,
5698      it);
5699 
5700    _view_inflate(it->item->deco_it_view, it, &it->item->deco_it_texts,
5701                  &it->item->deco_it_contents, EINA_FALSE);
5702    edje_object_part_swallow
5703      (it->item->deco_it_view,
5704      edje_object_data_get(it->item->deco_it_view, "mode_part"), VIEW(it));
5705 
5706    snprintf(buf, sizeof(buf), "elm,state,%s,active", sd->decorate_it_type);
5707    edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
5708    edje_object_signal_emit(VIEW(it), buf, "elm");
5709 
5710    it->want_unrealize = EINA_FALSE;
5711    evas_event_thaw(e);
5712    evas_event_thaw_eval(e);
5713 }
5714 
5715 static void
_decorate_item_set(Elm_Gen_Item * it)5716 _decorate_item_set(Elm_Gen_Item *it)
5717 {
5718    Evas *e;
5719    if (!it) return;
5720 
5721    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
5722 
5723    sd->mode_item = it;
5724    it->item->nocache_once = EINA_TRUE;
5725 
5726    ELM_SAFE_FREE(sd->scr_hold_timer, ecore_timer_del);
5727    elm_interface_scrollable_hold_set(sd->obj, EINA_TRUE);
5728    sd->scr_hold_timer = ecore_timer_add(SCR_HOLD_TIME, _scroll_hold_timer_cb, sd->obj);
5729 
5730    e = evas_object_evas_get(sd->obj);
5731    evas_event_freeze(e);
5732    _decorate_item_realize(it);
5733    if (it->item->group_item)
5734      evas_object_stack_above(it->item->VIEW(group_item), sd->stack[1]);
5735    _item_position
5736      (it, it->item->deco_it_view, it->item->scrl_x, it->item->scrl_y);
5737    evas_event_thaw(e);
5738    evas_event_thaw_eval(e);
5739 
5740 }
5741 
5742 static void
_decorate_item_unset(Elm_Genlist_Data * sd)5743 _decorate_item_unset(Elm_Genlist_Data *sd)
5744 {
5745    char buf[1024], buf2[1024];
5746    Elm_Gen_Item *it;
5747 
5748    if (!sd->mode_item) return;
5749 
5750    it = sd->mode_item;
5751    it->item->nocache_once = EINA_TRUE;
5752    it->decorate_it_set = EINA_FALSE;
5753 
5754    snprintf(buf, sizeof(buf), "elm,state,%s,passive", sd->decorate_it_type);
5755    snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished",
5756             sd->decorate_it_type);
5757    edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
5758    edje_object_signal_callback_add
5759      (it->item->deco_it_view, buf2, "elm", _decorate_item_finished_signal_cb,
5760      it);
5761    sd->mode_item = NULL;
5762 }
5763 
5764 static void
_elm_genlist_looping_up_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)5765 _elm_genlist_looping_up_cb(void *data,
5766                            Evas_Object *obj EINA_UNUSED,
5767                            const char *emission EINA_UNUSED,
5768                            const char *source EINA_UNUSED)
5769 {
5770    Evas_Object *genlist = data;
5771 
5772    ELM_GENLIST_DATA_GET(genlist, sd);
5773 
5774    Elm_Object_Item *eo_it = elm_genlist_last_item_get(genlist);
5775 
5776    elm_genlist_item_show(eo_it, ELM_GENLIST_ITEM_SCROLLTO_IN);
5777    elm_layout_signal_emit(genlist, "elm,action,looping,up,end", "elm");
5778    sd->item_looping_on = EINA_FALSE;
5779 
5780    if (!_elm_config->item_select_on_focus_disable)
5781      elm_genlist_item_selected_set(eo_it, EINA_TRUE);
5782    else
5783      elm_object_item_focus_set(eo_it, EINA_TRUE);
5784 }
5785 
5786 static void
_elm_genlist_looping_down_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)5787 _elm_genlist_looping_down_cb(void *data,
5788                              Evas_Object *obj EINA_UNUSED,
5789                              const char *emission EINA_UNUSED,
5790                              const char *source EINA_UNUSED)
5791 {
5792    Evas_Object *genlist = data;
5793 
5794    ELM_GENLIST_DATA_GET(genlist, sd);
5795 
5796    Elm_Object_Item *eo_it = elm_genlist_first_item_get(genlist);
5797 
5798    elm_genlist_item_show(eo_it, ELM_GENLIST_ITEM_SCROLLTO_IN);
5799    elm_layout_signal_emit(genlist, "elm,action,looping,down,end", "elm");
5800    sd->item_looping_on = EINA_FALSE;
5801 
5802    if (!_elm_config->item_select_on_focus_disable)
5803      elm_genlist_item_selected_set(eo_it, EINA_TRUE);
5804    else
5805      elm_object_item_focus_set(eo_it, EINA_TRUE);
5806 }
5807 
5808 static void
_evas_viewport_resize_cb(void * d,Evas * e EINA_UNUSED,void * ei EINA_UNUSED)5809 _evas_viewport_resize_cb(void *d, Evas *e EINA_UNUSED, void *ei EINA_UNUSED)
5810 {
5811    Elm_Genlist_Data *priv = d;
5812    evas_object_smart_changed(priv->pan_obj);
5813 }
5814 
5815 EOLIAN static void
_elm_genlist_efl_canvas_group_group_add(Eo * obj,Elm_Genlist_Data * priv)5816 _elm_genlist_efl_canvas_group_group_add(Eo *obj, Elm_Genlist_Data *priv)
5817 {
5818    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
5819    Elm_Genlist_Pan_Data *pan_data;
5820    Evas_Coord minw, minh;
5821    Evas *e = evas_object_evas_get(obj);
5822    int i;
5823 
5824    efl_canvas_group_add(efl_super(obj, MY_CLASS));
5825 
5826    priv->size_caches = eina_hash_pointer_new(_size_cache_free);
5827    priv->hit_rect = evas_object_rectangle_add(e);
5828    evas_object_smart_member_add(priv->hit_rect, obj);
5829    elm_widget_sub_object_add(obj, priv->hit_rect);
5830 
5831    /* common scroller hit rectangle setup */
5832    evas_object_color_set(priv->hit_rect, 0, 0, 0, 0);
5833    evas_object_show(priv->hit_rect);
5834    evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE);
5835 
5836    elm_widget_can_focus_set(obj, EINA_TRUE);
5837    elm_widget_on_show_region_hook_set(obj, NULL, _show_region_hook, NULL);
5838 
5839    if (!elm_layout_theme_set
5840        (obj, "genlist", "base", elm_widget_style_get(obj)))
5841      CRI("Failed to set layout!");
5842 
5843    elm_interface_scrollable_objects_set(obj, wd->resize_obj, priv->hit_rect);
5844 
5845    elm_interface_scrollable_bounce_allow_set
5846          (obj, EINA_FALSE, _elm_config->thumbscroll_bounce_enable);
5847    priv->v_bounce = _elm_config->thumbscroll_bounce_enable;
5848 
5849    elm_interface_scrollable_animate_start_cb_set(obj, _scroll_animate_start_cb);
5850    elm_interface_scrollable_animate_stop_cb_set(obj, _scroll_animate_stop_cb);
5851    elm_interface_scrollable_scroll_cb_set(obj, _scroll_cb);
5852    elm_interface_scrollable_drag_start_cb_set(obj, _scroll_drag_start_cb);
5853    elm_interface_scrollable_drag_stop_cb_set(obj, _scroll_drag_stop_cb);
5854    elm_interface_scrollable_edge_left_cb_set(obj, _edge_left_cb);
5855    elm_interface_scrollable_edge_right_cb_set(obj, _edge_right_cb);
5856    elm_interface_scrollable_edge_top_cb_set(obj, _edge_top_cb);
5857    elm_interface_scrollable_edge_bottom_cb_set(obj, _edge_bottom_cb);
5858    elm_interface_scrollable_vbar_drag_cb_set(obj, _vbar_drag_cb);
5859    elm_interface_scrollable_vbar_press_cb_set(obj, _vbar_press_cb);
5860    elm_interface_scrollable_vbar_unpress_cb_set(obj, _vbar_unpress_cb);
5861    elm_interface_scrollable_hbar_drag_cb_set(obj, _hbar_drag_cb);
5862    elm_interface_scrollable_hbar_press_cb_set(obj, _hbar_press_cb);
5863    elm_interface_scrollable_hbar_unpress_cb_set(obj, _hbar_unpress_cb);
5864    elm_interface_scrollable_content_min_limit_cb_set(obj, _content_min_limit_cb);
5865 
5866    priv->mode = ELM_LIST_SCROLL;
5867    priv->max_items_per_block = MAX_ITEMS_PER_BLOCK;
5868    priv->item_cache_max = priv->max_items_per_block * 2;
5869    priv->longpress_timeout = _elm_config->longpress_timeout;
5870    priv->highlight = EINA_TRUE;
5871    priv->pin_item = NULL;
5872    priv->pin_item_top = EINA_FALSE;
5873 
5874    priv->pan_obj = efl_add(MY_PAN_CLASS, e);
5875    pan_data = efl_data_scope_get(priv->pan_obj, MY_PAN_CLASS);
5876    efl_data_ref(obj, MY_CLASS);
5877    pan_data->wobj = obj;
5878    pan_data->wsd = priv;
5879 
5880    for (i = 0; i < 2; i++)
5881      {
5882         priv->stack[i] = evas_object_rectangle_add(e);
5883         evas_object_smart_member_add(priv->stack[i], priv->pan_obj);
5884      }
5885 
5886    elm_interface_scrollable_extern_pan_set(obj, priv->pan_obj);
5887 
5888    edje_object_size_min_calc(wd->resize_obj, &minw, &minh);
5889    evas_object_size_hint_min_set(obj, minw, minh);
5890 
5891    _mirrored_set(obj, efl_ui_mirrored_get(obj));
5892 
5893    elm_layout_sizing_eval(obj);
5894 
5895    edje_object_signal_callback_add(wd->resize_obj, "elm,looping,up,done", "elm", _elm_genlist_looping_up_cb, obj);
5896    edje_object_signal_callback_add(wd->resize_obj, "elm,looping,down,done", "elm", _elm_genlist_looping_down_cb, obj);
5897    evas_event_callback_add(e,
5898                            EVAS_CALLBACK_CANVAS_VIEWPORT_RESIZE,
5899                            _evas_viewport_resize_cb, priv);
5900 }
5901 
5902 EOLIAN static void
_elm_genlist_efl_canvas_group_group_del(Eo * obj,Elm_Genlist_Data * sd)5903 _elm_genlist_efl_canvas_group_group_del(Eo *obj, Elm_Genlist_Data *sd)
5904 {
5905    int i;
5906 
5907    elm_genlist_clear(obj);
5908    _item_cache_zero(sd);
5909 
5910    efl_canvas_group_del(efl_super(obj, MY_CLASS));
5911 
5912    for (i = 0; i < 2; i++)
5913      ELM_SAFE_FREE(sd->stack[i], evas_object_del);
5914 
5915    evas_event_callback_del_full(evas_object_evas_get(obj),
5916                                 EVAS_CALLBACK_CANVAS_VIEWPORT_RESIZE,
5917                                 _evas_viewport_resize_cb, sd);
5918 
5919    ELM_SAFE_FREE(sd->update_job, ecore_job_del);
5920    ELM_SAFE_FREE(sd->pan_obj, evas_object_del);
5921    ELM_SAFE_FREE(sd->queue_idle_enterer, ecore_idle_enterer_del);
5922    ELM_SAFE_FREE(sd->must_recalc_idler, ecore_idler_del);
5923    ELM_SAFE_FREE(sd->multi_timer, ecore_timer_del);
5924    ELM_SAFE_FREE(sd->size_caches, eina_hash_free);
5925 
5926    eina_stringshare_replace(&sd->decorate_it_type, NULL);
5927 
5928    eina_hash_free(sd->content_item_map);
5929    _elm_genlist_tree_effect_stop(sd);
5930 }
5931 
5932 EOLIAN static void
_elm_genlist_efl_gfx_entity_position_set(Eo * obj,Elm_Genlist_Data * sd,Eina_Position2D pos)5933 _elm_genlist_efl_gfx_entity_position_set(Eo *obj, Elm_Genlist_Data *sd, Eina_Position2D pos)
5934 {
5935    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y))
5936      return;
5937 
5938    efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
5939    efl_gfx_entity_position_set(sd->hit_rect, pos);
5940 }
5941 
5942 EOLIAN static void
_elm_genlist_efl_gfx_entity_size_set(Eo * obj,Elm_Genlist_Data * sd,Eina_Size2D sz)5943 _elm_genlist_efl_gfx_entity_size_set(Eo *obj, Elm_Genlist_Data *sd, Eina_Size2D sz)
5944 {
5945    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, sz.w, sz.h))
5946      return;
5947 
5948    efl_gfx_entity_size_set(sd->hit_rect, sz);
5949    if ((sd->queue) && (!sd->queue_idle_enterer) && (sz.w > 0))
5950      _requeue_idle_enterer(sd);
5951 
5952    efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz);
5953 }
5954 
5955 EOLIAN static void
_elm_genlist_efl_canvas_group_group_member_add(Eo * obj,Elm_Genlist_Data * sd,Evas_Object * member)5956 _elm_genlist_efl_canvas_group_group_member_add(Eo *obj, Elm_Genlist_Data *sd, Evas_Object *member)
5957 {
5958    efl_canvas_group_member_add(efl_super(obj, MY_CLASS), member);
5959 
5960    if (sd->hit_rect)
5961      evas_object_raise(sd->hit_rect);
5962 }
5963 
5964 static void
_access_obj_process(Elm_Genlist_Data * sd,Eina_Bool is_access)5965 _access_obj_process(Elm_Genlist_Data *sd, Eina_Bool is_access)
5966 {
5967    Item_Block *itb;
5968    Eina_Bool done = EINA_FALSE;
5969 
5970    EINA_INLIST_FOREACH(sd->blocks, itb)
5971      {
5972         if (itb->realized)
5973           {
5974              Eina_List *l;
5975              Elm_Gen_Item *it;
5976 
5977              done = EINA_TRUE;
5978              EINA_LIST_FOREACH(itb->items, l, it)
5979                {
5980                   if (!it->realized || it->hide) continue;
5981                   if (is_access) _access_widget_item_register(it);
5982                   else
5983                     _elm_access_widget_item_unregister(it->base);
5984                }
5985           }
5986         else if (done) break;
5987      }
5988 }
5989 
5990 EOLIAN static void
_elm_genlist_efl_ui_widget_on_access_update(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool acs)5991 _elm_genlist_efl_ui_widget_on_access_update(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool acs)
5992 {
5993    _elm_genlist_smart_focus_next_enable = acs;
5994    _access_obj_process(sd, _elm_genlist_smart_focus_next_enable);
5995 }
5996 
5997 EAPI Evas_Object *
elm_genlist_add(Evas_Object * parent)5998 elm_genlist_add(Evas_Object *parent)
5999 {
6000    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
6001    return elm_legacy_add(MY_CLASS, parent);
6002 }
6003 
6004 static void
_genlist_element_focused(void * data,const Efl_Event * ev)6005 _genlist_element_focused(void *data, const Efl_Event *ev)
6006 {
6007    ELM_GENLIST_DATA_GET(data, pd);
6008    Efl_Ui_Widget *focused = efl_ui_focus_manager_focus_get(ev->object);
6009    Elm_Widget_Item *item;
6010 
6011    if (!focused || focused == data) return;
6012 
6013    item = efl_ui_focus_parent_provider_gen_item_fetch(pd->provider, focused);
6014 
6015    EINA_SAFETY_ON_FALSE_RETURN(efl_isa(item, ELM_GENLIST_ITEM_CLASS));
6016    elm_object_item_focus_set(item, EINA_TRUE);
6017 }
6018 
6019 EOLIAN static Eo *
_elm_genlist_efl_object_constructor(Eo * obj,Elm_Genlist_Data * sd)6020 _elm_genlist_efl_object_constructor(Eo *obj, Elm_Genlist_Data *sd)
6021 {
6022    legacy_efl_ui_focus_manager_widget_legacy_signals(obj, obj);
6023    obj = efl_constructor(efl_super(obj, MY_CLASS));
6024 
6025    sd->content_item_map = eina_hash_pointer_new(NULL);
6026    sd->provider = efl_add(EFL_UI_FOCUS_PARENT_PROVIDER_GEN_CLASS, obj,
6027     efl_ui_focus_parent_provider_gen_container_set(efl_added, obj),
6028     efl_ui_focus_parent_provider_gen_content_item_map_set(efl_added, sd->content_item_map));
6029 
6030    sd->obj = obj;
6031 
6032    efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
6033    evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
6034    efl_access_object_role_set(obj, EFL_ACCESS_ROLE_LIST);
6035 
6036    efl_event_callback_add(obj, EFL_UI_FOCUS_MANAGER_EVENT_MANAGER_FOCUS_CHANGED, _genlist_element_focused, obj);
6037 
6038    return obj;
6039 }
6040 
6041 static void
_internal_elm_genlist_clear(Evas_Object * obj)6042 _internal_elm_genlist_clear(Evas_Object *obj)
6043 {
6044    ELM_GENLIST_DATA_GET(obj, sd);
6045    Elm_Gen_Item *it;
6046    Evas *e = evas_object_evas_get(sd->obj);
6047 
6048    _elm_genlist_item_unfocused(sd->focused_item);
6049    if (sd->mode_item) sd->mode_item = NULL;
6050 
6051    ELM_SAFE_FREE(sd->state, eina_inlist_sorted_state_free);
6052 
6053    sd->filter_data = NULL;
6054    if (sd->filter_queue)
6055      ELM_SAFE_FREE(sd->queue_filter_enterer, ecore_idle_enterer_del);
6056    ELM_SAFE_FREE(sd->filter_queue, eina_list_free);
6057    ELM_SAFE_FREE(sd->filtered_list, eina_list_free);
6058 
6059    evas_event_freeze(e);
6060 
6061    // Do not use EINA_INLIST_FOREACH or EINA_INLIST_FOREACH_SAFE
6062    // because sd->items can be modified inside elm_widget_item_del()
6063    while (sd->items)
6064      {
6065         it = EINA_INLIST_CONTAINER_GET(sd->items, Elm_Gen_Item);
6066         efl_del(EO_OBJ(it));
6067      }
6068 
6069    sd->pan_changed = EINA_TRUE;
6070    if (!sd->queue)
6071      {
6072         sd->anchor_item = NULL;
6073         ELM_SAFE_FREE(sd->queue_idle_enterer, ecore_idle_enterer_del);
6074         ELM_SAFE_FREE(sd->must_recalc_idler, ecore_idler_del);
6075         ELM_SAFE_FREE(sd->reorder_move_animator, ecore_animator_del);
6076         sd->reorder_old_pan_y = 0;
6077      }
6078 
6079    if (sd->selected) ELM_SAFE_FREE(sd->selected, eina_list_free);
6080 
6081    sd->show_item = NULL;
6082 
6083    sd->pan_x = 0;
6084    sd->pan_y = 0;
6085    sd->minw = 0;
6086    sd->minh = 0;
6087 
6088    if (sd->pan_obj)
6089      {
6090         evas_object_size_hint_min_set(sd->pan_obj, sd->minw, sd->minh);
6091         efl_event_callback_legacy_call
6092               (sd->pan_obj, ELM_PAN_EVENT_CHANGED, NULL);
6093      }
6094    elm_layout_sizing_eval(sd->obj);
6095    elm_interface_scrollable_content_region_show(obj, 0, 0, 0, 0);
6096 
6097    _elm_genlist_tree_effect_stop(sd);
6098 
6099    ELM_SAFE_FREE(sd->multi_timer, ecore_timer_del);
6100    ELM_SAFE_FREE(sd->update_job, ecore_job_del);
6101    ELM_SAFE_FREE(sd->queue_idle_enterer, ecore_idle_enterer_del);
6102    ELM_SAFE_FREE(sd->must_recalc_idler, ecore_idler_del);
6103    ELM_SAFE_FREE(sd->event_block_rect, evas_object_del);
6104    ELM_SAFE_FREE(sd->scr_hold_timer, ecore_timer_del);
6105    ELM_SAFE_FREE(sd->queue, eina_list_free);
6106 
6107    evas_event_thaw(e);
6108    evas_event_thaw_eval(e);
6109 
6110    _elm_widget_focus_highlight_start(obj);
6111 }
6112 
6113 /* Return EINA_TRUE if the item is deleted in this function */
6114 static Eina_Bool
_item_select(Elm_Gen_Item * it)6115 _item_select(Elm_Gen_Item *it)
6116 {
6117    Evas_Object *obj = WIDGET(it);
6118    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
6119    Elm_Object_Item *eo_it = EO_OBJ(it);
6120    Eina_Bool r = EINA_FALSE;
6121 
6122    if (elm_wdg_item_disabled_get(eo_it)) return EINA_FALSE;
6123    if (_is_no_select(it) || (it->decorate_it_set)) return EINA_FALSE;
6124    if ((sd->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS) &&
6125        (it->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS) && it->selected)
6126      return EINA_FALSE;
6127 
6128    if (!sd->multi)
6129      {
6130         const Eina_List *l, *ll;
6131         Elm_Object_Item *eo_it2;
6132         EINA_LIST_FOREACH_SAFE(sd->selected, l, ll, eo_it2)
6133          {
6134             ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
6135             if (it2 != it) _item_unselect(it2);
6136          }
6137      }
6138 
6139    if (!it->selected)
6140      {
6141         it->selected = EINA_TRUE;
6142         sd->selected =
6143           eina_list_append(sd->selected, eo_it);
6144      }
6145 
6146    efl_ref(eo_it);
6147 
6148    elm_object_item_focus_set(eo_it, EINA_TRUE);
6149    if ((it->base)->on_deletion) goto item_deleted;
6150    _elm_genlist_item_content_focus_set(it, ELM_FOCUS_PREVIOUS);
6151    sd->last_selected_item = eo_it;
6152    _item_highlight(it);
6153 
6154    if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), eo_it);
6155    // delete item if it's requested deletion in the above callbacks.
6156    if ((it->base)->on_deletion) goto item_deleted;
6157    evas_object_smart_callback_call(WIDGET(it), "selected", eo_it);
6158    if (_elm_config->atspi_mode)
6159      efl_access_state_changed_signal_emit(eo_it, EFL_ACCESS_STATE_TYPE_SELECTED, EINA_TRUE);
6160    // delete item if it's requested deletion in the above callbacks.
6161    if ((it->base)->on_deletion)
6162      {
6163         r = EINA_TRUE;
6164         goto item_deleted;
6165      }
6166 
6167    if (!(sd->focus_on_selection_enabled || _elm_config->item_select_on_focus_disable))
6168      {
6169         efl_ui_focus_manager_focus_set(obj, it->base->eo_obj);
6170      }
6171 
6172  item_deleted:
6173    efl_unref(eo_it);
6174 
6175    return r;
6176 }
6177 
6178 EOLIAN static Evas_Object *
_elm_genlist_item_elm_widget_item_part_content_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it,const char * part)6179 _elm_genlist_item_elm_widget_item_part_content_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it, const char * part)
6180 {
6181    Evas_Object *ret = NULL;
6182    if (it->deco_all_view)
6183      ret = edje_object_part_swallow_get(it->deco_all_view, part);
6184    else if (it->decorate_it_set)
6185      ret = edje_object_part_swallow_get(it->item->deco_it_view, part);
6186    if (!ret)
6187      {
6188         if (part)
6189           ret = edje_object_part_swallow_get(VIEW(it), part);
6190         else
6191           ret = edje_object_part_swallow_get(VIEW(it), "elm.swallow.icon");
6192      }
6193    return ret;
6194 }
6195 
6196 EOLIAN static const char *
_elm_genlist_item_elm_widget_item_part_text_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it,const char * part)6197 _elm_genlist_item_elm_widget_item_part_text_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it, const char * part)
6198 {
6199    if (!it->itc->func.text_get) return NULL;
6200    const char *ret = NULL;
6201    if (it->deco_all_view)
6202      ret = edje_object_part_text_get(it->deco_all_view, part);
6203    else if (it->decorate_it_set)
6204      ret = edje_object_part_text_get(it->item->deco_it_view, part);
6205    if (!ret)
6206      {
6207         if (part)
6208           ret = edje_object_part_text_get(VIEW(it), part);
6209         else
6210           ret = edje_object_part_text_get(VIEW(it), "elm.text");
6211      }
6212    return ret;
6213 }
6214 
6215 EOLIAN static void
_elm_genlist_item_elm_widget_item_disable(Eo * eo_it,Elm_Gen_Item * it)6216 _elm_genlist_item_elm_widget_item_disable(Eo *eo_it, Elm_Gen_Item *it)
6217 {
6218    Eina_List *l;
6219    Evas_Object *obj;
6220 
6221    _item_unselect(it);
6222    if (eo_it == it->item->wsd->focused_item)
6223      _elm_genlist_item_unfocused(eo_it);
6224    ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
6225 
6226    if (it->realized)
6227      {
6228         if (elm_wdg_item_disabled_get(EO_OBJ(it)))
6229           {
6230              edje_object_signal_emit(VIEW(it), SIGNAL_DISABLED, "elm");
6231              if (it->deco_all_view)
6232                edje_object_signal_emit
6233                  (it->deco_all_view, SIGNAL_DISABLED, "elm");
6234           }
6235         else
6236           {
6237              edje_object_signal_emit(VIEW(it), SIGNAL_ENABLED, "elm");
6238              if (it->deco_all_view)
6239                edje_object_signal_emit
6240                  (it->deco_all_view, SIGNAL_ENABLED, "elm");
6241           }
6242         EINA_LIST_FOREACH(it->contents, l, obj)
6243           elm_widget_disabled_set(obj, elm_wdg_item_disabled_get(EO_OBJ(it)));
6244      }
6245 }
6246 
6247 EOLIAN static void
_elm_genlist_item_elm_widget_item_del_pre(Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)6248 _elm_genlist_item_elm_widget_item_del_pre(Eo *eo_it EINA_UNUSED,
6249                                           Elm_Gen_Item *it)
6250 {
6251    /* This item is getting removed from a callback that triggered in the
6252       _item_select(). Just pend removing. Because this will be removed right
6253       after in the _item_select(). So pratically, this item won't be
6254       dangled. */
6255    if (_elm_config->atspi_mode)
6256      efl_access_children_changed_del_signal_emit(WIDGET(it),eo_it);
6257 
6258    _item_del(it);
6259 }
6260 
6261 EOLIAN static void
_elm_genlist_item_elm_widget_item_signal_emit(Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it,const char * emission,const char * source)6262 _elm_genlist_item_elm_widget_item_signal_emit(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it, const char *emission, const char *source)
6263 {
6264    if (!it->realized)
6265      {
6266         WRN("Item is not realized yet");
6267         return;
6268      }
6269    edje_object_signal_emit(VIEW(it), emission, source);
6270    if (it->deco_all_view)
6271      edje_object_signal_emit(it->deco_all_view, emission, source);
6272 }
6273 
6274 EOLIAN static void
_elm_genlist_item_elm_widget_item_style_set(Eo * eo_it,Elm_Gen_Item * it,const char * style)6275 _elm_genlist_item_elm_widget_item_style_set(Eo *eo_it,
6276                                             Elm_Gen_Item *it,
6277                                             const char *style)
6278 {
6279    if (it->itc && !strcmp(it->itc->item_style, style)) return;
6280 
6281    Elm_Genlist_Item_Class *itc = elm_genlist_item_class_new();
6282 
6283    itc->item_style = style;
6284    if (it->itc)
6285      {
6286         itc->func.text_get = it->itc->func.text_get;
6287         itc->func.content_get = it->itc->func.content_get;
6288         itc->func.state_get = it->itc->func.state_get;
6289         itc->func.filter_get = it->itc->func.filter_get;
6290         itc->func.reusable_content_get = it->itc->func.reusable_content_get;
6291         itc->decorate_item_style = it->itc->decorate_item_style;
6292         itc->decorate_all_item_style = it->itc->decorate_all_item_style;
6293      }
6294 
6295    elm_genlist_item_item_class_update(eo_it, itc);
6296    elm_genlist_item_class_free(itc);
6297 }
6298 
6299 EOLIAN static const char *
_elm_genlist_item_elm_widget_item_style_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)6300 _elm_genlist_item_elm_widget_item_style_get(const Eo *eo_it EINA_UNUSED,
6301                                             Elm_Gen_Item *it)
6302 {
6303    if (it->itc) return it->itc->item_style;
6304    else return NULL;
6305 }
6306 
6307 EOLIAN static void
_elm_genlist_item_elm_widget_item_item_focus_set(Eo * eo_it,Elm_Gen_Item * it,Eina_Bool focused)6308 _elm_genlist_item_elm_widget_item_item_focus_set(Eo *eo_it, Elm_Gen_Item *it, Eina_Bool focused)
6309 {
6310    Evas_Object *obj = WIDGET(it);
6311    ELM_GENLIST_DATA_GET(obj, sd);
6312 
6313    if (focused)
6314      {
6315         sd->last_focused_item = eo_it;
6316         if (!elm_object_focus_get(obj))
6317           elm_object_focus_set(obj, EINA_TRUE);
6318 
6319         if (!elm_object_focus_get(obj))
6320           return;
6321 
6322         if (eo_it != sd->focused_item)
6323           {
6324              if (sd->focused_item)
6325                _elm_genlist_item_unfocused(sd->focused_item);
6326              _elm_genlist_item_focused(eo_it);
6327 
6328              /* If item is not realized state, widget couldn't get focus_highlight data. */
6329              if (it->realized)
6330                {
6331                   _elm_widget_item_highlight_in_theme(obj, EO_OBJ(it));
6332                   _elm_widget_highlight_in_theme_update(obj);
6333                   _elm_widget_focus_highlight_start(obj);
6334                   efl_ui_focus_manager_focus_set(it->base->widget, eo_it);
6335                   sd->focus_on_realization = NULL;
6336                }
6337              else
6338                {
6339                   sd->focus_on_realization = it;
6340                }
6341           }
6342      }
6343    else
6344      {
6345         if (!efl_ui_focus_object_focus_get(obj))
6346           return;
6347         _elm_genlist_item_unfocused(eo_it);
6348      }
6349 }
6350 
6351 EOLIAN static Eina_Bool
_elm_genlist_item_elm_widget_item_item_focus_get(const Eo * eo_it,Elm_Gen_Item * it)6352 _elm_genlist_item_elm_widget_item_item_focus_get(const Eo *eo_it, Elm_Gen_Item *it)
6353 {
6354    Evas_Object *obj = WIDGET(it);
6355    ELM_GENLIST_DATA_GET(obj, sd);
6356 
6357    if (eo_it == sd->focused_item)
6358      return EINA_TRUE;
6359 
6360    return EINA_FALSE;
6361 }
6362 
6363 EOLIAN static Eo *
_elm_genlist_item_efl_object_constructor(Eo * eo_it,Elm_Gen_Item * it)6364 _elm_genlist_item_efl_object_constructor(Eo *eo_it, Elm_Gen_Item *it)
6365 {
6366    eo_it = efl_constructor(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS));
6367 
6368    it->base = efl_data_scope_get(eo_it, ELM_WIDGET_ITEM_CLASS);
6369    efl_access_object_role_set(eo_it, EFL_ACCESS_ROLE_LIST_ITEM);
6370 
6371    return eo_it;
6372 }
6373 
6374 static Elm_Gen_Item *
_elm_genlist_item_new(Elm_Genlist_Data * sd,const Elm_Genlist_Item_Class * itc,const void * data,Elm_Object_Item * eo_parent,Elm_Genlist_Item_Type type,Evas_Smart_Cb func,const void * func_data)6375 _elm_genlist_item_new(Elm_Genlist_Data *sd,
6376                       const Elm_Genlist_Item_Class *itc,
6377                       const void *data,
6378                       Elm_Object_Item *eo_parent,
6379                       Elm_Genlist_Item_Type type,
6380                       Evas_Smart_Cb func,
6381                       const void *func_data)
6382 {
6383    Elm_Gen_Item *it2;
6384    int depth = 0;
6385 
6386    if (!itc) return NULL;
6387 
6388    Eo *eo_it = efl_add(ELM_GENLIST_ITEM_CLASS, sd->obj);
6389    if (!eo_it) return NULL;
6390    ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
6391 
6392    it->itc = itc;
6393    elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)itc);
6394 
6395    ELM_GENLIST_ITEM_DATA_GET(eo_parent, parent);
6396    WIDGET_ITEM_DATA_SET(EO_OBJ(it), data);
6397    it->parent = parent;
6398    it->func.func = func;
6399    it->func.data = func_data;
6400 
6401    it->item = ELM_NEW(Elm_Gen_Item_Type);
6402    it->item->wsd = sd;
6403    it->item->type = type;
6404    it->item->order_num_in = -1;
6405 
6406    if (it->parent)
6407      {
6408         if (it->parent->item->type & ELM_GENLIST_ITEM_GROUP)
6409           it->item->group_item = parent;
6410         else if (it->parent->item->group_item)
6411           it->item->group_item = it->parent->item->group_item;
6412      }
6413    for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
6414      {
6415         if (!(it2->parent->item->type & ELM_GENLIST_ITEM_GROUP)) depth += 1;
6416      }
6417    it->item->expanded_depth = depth;
6418    sd->item_count++;
6419 
6420    return it;
6421 }
6422 
6423 static int
_elm_genlist_item_compare(const void * data,const void * data1)6424 _elm_genlist_item_compare(const void *data,
6425                           const void *data1)
6426 {
6427    const Elm_Gen_Item *it, *item1;
6428 
6429    it = ELM_GEN_ITEM_FROM_INLIST(data);
6430    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
6431    return it->item->wsd->item_compare_cb(EO_OBJ(it), EO_OBJ(item1));
6432 }
6433 
6434 static int
_elm_genlist_item_list_compare(const void * data,const void * data1)6435 _elm_genlist_item_list_compare(const void *data,
6436                                const void *data1)
6437 {
6438    const Elm_Gen_Item *it = data;
6439    const Elm_Gen_Item *item1 = data1;
6440 
6441    return it->item->wsd->item_compare_cb(EO_OBJ(it), EO_OBJ(item1));
6442 }
6443 
6444 static int
_elm_genlist_eo_item_list_compare(const void * data,const void * data1)6445 _elm_genlist_eo_item_list_compare(const void *data,
6446                                const void *data1)
6447 {
6448    const Elm_Object_Item *eo_it = data;
6449    const Elm_Object_Item *eo_item1 = data1;
6450    ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
6451 
6452    return it->item->wsd->item_compare_cb(eo_it, eo_item1);
6453 }
6454 
6455 EOLIAN static unsigned int
_elm_genlist_items_count(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)6456 _elm_genlist_items_count(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
6457 {
6458    return sd->item_count;
6459 }
6460 
6461 static Eina_List *
_list_last_recursive(Eina_List * list)6462 _list_last_recursive(Eina_List *list)
6463 {
6464    Eina_List *ll, *ll2;
6465    Elm_Object_Item *eo_it2;
6466 
6467    ll = eina_list_last(list);
6468    if (!ll) return NULL;
6469 
6470    eo_it2 = ll->data;
6471    ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
6472 
6473    if (it2->item->items)
6474      {
6475         ll2 = _list_last_recursive(it2->item->items);
6476         if (ll2)
6477           {
6478              return ll2;
6479           }
6480      }
6481 
6482    return ll;
6483 }
6484 
6485 EOLIAN static Elm_Object_Item*
_elm_genlist_item_append(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,const Elm_Genlist_Item_Class * itc,const void * data,Elm_Object_Item * eo_parent,Elm_Genlist_Item_Type type,Evas_Smart_Cb func,const void * func_data)6486 _elm_genlist_item_append(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *eo_parent, Elm_Genlist_Item_Type type, Evas_Smart_Cb func, const void *func_data)
6487 {
6488    Elm_Gen_Item *it;
6489 
6490    if (eo_parent)
6491      {
6492         ELM_GENLIST_ITEM_DATA_GET(eo_parent, parent);
6493         ELM_GENLIST_ITEM_CHECK_OR_RETURN(parent, NULL);
6494         EINA_SAFETY_ON_FALSE_RETURN_VAL((obj == WIDGET(parent)), NULL);
6495      }
6496 
6497    it = _elm_genlist_item_new
6498        (sd, itc, data, eo_parent, type, func, func_data);
6499    if (!it) return NULL;
6500 
6501    if (!it->parent)
6502      {
6503         if (it->item->type & ELM_GENLIST_ITEM_GROUP)
6504           sd->group_items = eina_list_append(sd->group_items, it);
6505         sd->items = eina_inlist_append(sd->items, EINA_INLIST_GET(it));
6506         it->item->rel = NULL;
6507      }
6508    else
6509      {
6510         Elm_Object_Item *eo_it2 = NULL;
6511         Eina_List *ll = _list_last_recursive(it->parent->item->items);
6512 
6513         if (ll) eo_it2 = ll->data;
6514         if (!it->parent->item->items)
6515           sd->top_level_parent_items++;
6516         it->parent->item->items =
6517           eina_list_append(it->parent->item->items, EO_OBJ(it));
6518         if (!eo_it2) eo_it2 = EO_OBJ(it->parent);
6519         ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
6520         sd->items = eina_inlist_append_relative
6521            (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(it2));
6522         it->item->rel = it2;
6523         it2->item->rel_revs = eina_list_append(it2->item->rel_revs, it);
6524         _item_expanded_set_noevent(it->parent, EINA_TRUE);
6525      }
6526    it->item->before = EINA_FALSE;
6527    _item_queue(sd, it, NULL);
6528 
6529    return EO_OBJ(it);
6530 }
6531 
6532 EOLIAN static Elm_Object_Item*
_elm_genlist_item_prepend(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,const Elm_Genlist_Item_Class * itc,const void * data,Elm_Object_Item * eo_parent,Elm_Genlist_Item_Type type,Evas_Smart_Cb func,const void * func_data)6533 _elm_genlist_item_prepend(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *eo_parent, Elm_Genlist_Item_Type type, Evas_Smart_Cb func, const void *func_data)
6534 {
6535    Elm_Gen_Item *it;
6536 
6537    if (eo_parent)
6538      {
6539         ELM_GENLIST_ITEM_DATA_GET(eo_parent, parent);
6540         ELM_GENLIST_ITEM_CHECK_OR_RETURN(parent, NULL);
6541         EINA_SAFETY_ON_FALSE_RETURN_VAL((obj == WIDGET(parent)), NULL);
6542         /* first sub-item should allways be appended */
6543         if (!parent->item->items)
6544           return _elm_genlist_item_append(obj, sd, itc, data, eo_parent, type, func, func_data);
6545      }
6546 
6547    it = _elm_genlist_item_new
6548        (sd, itc, data, eo_parent, type, func, func_data);
6549    if (!it) return NULL;
6550 
6551    if (!it->parent)
6552      {
6553         if (it->item->type & ELM_GENLIST_ITEM_GROUP)
6554           sd->group_items = eina_list_prepend(sd->group_items, it);
6555         sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(it));
6556         it->item->rel = NULL;
6557      }
6558    else
6559      {
6560         Elm_Object_Item *eo_it2 = NULL;
6561         Eina_List *ll = it->parent->item->items;
6562 
6563         if (ll) eo_it2 = ll->data;
6564         if (!it->parent->item->items)
6565           sd->top_level_parent_items++;
6566         it->parent->item->items =
6567           eina_list_prepend(it->parent->item->items, EO_OBJ(it));
6568         if (!eo_it2) eo_it2 = EO_OBJ(it->parent);
6569         ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
6570         sd->items = eina_inlist_prepend_relative
6571            (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(it2));
6572         it->item->rel = it2;
6573         it2->item->rel_revs = eina_list_append(it2->item->rel_revs, it);
6574         _item_expanded_set_noevent(it->parent, EINA_TRUE);
6575      }
6576    it->item->before = EINA_TRUE;
6577    _item_queue(sd, it, NULL);
6578 
6579    return EO_OBJ(it);
6580 }
6581 
6582 EOLIAN static Elm_Object_Item*
_elm_genlist_item_insert_after(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,const Elm_Genlist_Item_Class * itc,const void * data,Elm_Object_Item * eo_parent,Elm_Object_Item * eo_after,Elm_Genlist_Item_Type type,Evas_Smart_Cb func,const void * func_data)6583 _elm_genlist_item_insert_after(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *eo_parent, Elm_Object_Item *eo_after, Elm_Genlist_Item_Type type, Evas_Smart_Cb func, const void *func_data)
6584 {
6585    EINA_SAFETY_ON_NULL_RETURN_VAL(eo_after, NULL);
6586    ELM_GENLIST_ITEM_DATA_GET(eo_after, after);
6587    Elm_Gen_Item *it;
6588 
6589    ELM_GENLIST_ITEM_CHECK_OR_RETURN(after, NULL);
6590    EINA_SAFETY_ON_FALSE_RETURN_VAL((obj == WIDGET(after)), NULL);
6591    if (eo_parent)
6592      {
6593         ELM_GENLIST_ITEM_DATA_GET(eo_parent, parent);
6594         ELM_GENLIST_ITEM_CHECK_OR_RETURN(parent, NULL);
6595         EINA_SAFETY_ON_FALSE_RETURN_VAL((obj == WIDGET(parent)), NULL);
6596      }
6597 
6598    /* It makes no sense to insert after in an empty list with after !=
6599     * NULL, something really bad is happening in your app. */
6600    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->items, NULL);
6601 
6602    it = _elm_genlist_item_new
6603        (sd, itc, data, eo_parent, type, func, func_data);
6604    if (!it) return NULL;
6605 
6606    if (!it->parent)
6607      {
6608         if ((it->item->type & ELM_GENLIST_ITEM_GROUP) &&
6609             (after->item->type & ELM_GENLIST_ITEM_GROUP))
6610           sd->group_items = eina_list_append_relative
6611              (sd->group_items, it, after);
6612         else if (it->item->type & ELM_GENLIST_ITEM_GROUP)
6613           CRI("GROUP ITEM INSERT FAILED: NON-GROUP ITEM PASSED AS 'after'!");
6614      }
6615    else
6616      {
6617         if (!it->parent->item->items)
6618           sd->top_level_parent_items++;
6619         it->parent->item->items =
6620           eina_list_append_relative(it->parent->item->items, EO_OBJ(it), eo_after);
6621         _item_expanded_set_noevent(it->parent, EINA_TRUE);
6622      }
6623 
6624    if (after->item->items)
6625      {
6626         Eina_List *ll = _list_last_recursive(after->item->items);
6627         if (ll)
6628           {
6629              eo_after = ll->data;
6630              after = efl_data_scope_get(eo_after, ELM_GENLIST_ITEM_CLASS);
6631           }
6632      }
6633 
6634    sd->items = eina_inlist_append_relative
6635        (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
6636 
6637    it->item->rel = after;
6638    after->item->rel_revs = eina_list_append(after->item->rel_revs, it);
6639    it->item->before = EINA_FALSE;
6640    _item_queue(sd, it, NULL);
6641 
6642    return EO_OBJ(it);
6643 }
6644 
6645 EOLIAN static Elm_Object_Item*
_elm_genlist_item_insert_before(Eo * obj,Elm_Genlist_Data * sd,const Elm_Genlist_Item_Class * itc,const void * data,Elm_Object_Item * eo_parent,Elm_Object_Item * eo_before,Elm_Genlist_Item_Type type,Evas_Smart_Cb func,const void * func_data)6646 _elm_genlist_item_insert_before(Eo *obj, Elm_Genlist_Data *sd, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *eo_parent, Elm_Object_Item *eo_before, Elm_Genlist_Item_Type type, Evas_Smart_Cb func, const void *func_data)
6647 {
6648    EINA_SAFETY_ON_NULL_RETURN_VAL(eo_before, NULL);
6649    ELM_GENLIST_ITEM_DATA_GET(eo_before, before);
6650    Elm_Gen_Item *it;
6651 
6652    ELM_GENLIST_ITEM_CHECK_OR_RETURN(before, NULL);
6653    EINA_SAFETY_ON_FALSE_RETURN_VAL((obj == WIDGET(before)), NULL);
6654    if (eo_parent)
6655      {
6656         ELM_GENLIST_ITEM_DATA_GET(eo_parent, parent);
6657         ELM_GENLIST_ITEM_CHECK_OR_RETURN(parent, NULL);
6658         EINA_SAFETY_ON_FALSE_RETURN_VAL((obj == WIDGET(parent)), NULL);
6659      }
6660 
6661    /* It makes no sense to insert before in an empty list with before
6662     * != NULL, something really bad is happening in your app. */
6663    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->items, NULL);
6664 
6665    it = _elm_genlist_item_new
6666        (sd, itc, data, eo_parent, type, func, func_data);
6667    if (!it) return NULL;
6668 
6669    if (!it->parent)
6670      {
6671         if ((it->item->type & ELM_GENLIST_ITEM_GROUP) &&
6672             (before->item->type & ELM_GENLIST_ITEM_GROUP))
6673           sd->group_items =
6674             eina_list_prepend_relative(sd->group_items, it, before);
6675         else if (it->item->type & ELM_GENLIST_ITEM_GROUP)
6676           CRI("GROUP ITEM INSERT FAILED: NON-GROUP ITEM PASSED AS 'after'!");
6677      }
6678    else
6679      {
6680         if (!it->parent->item->items)
6681           sd->top_level_parent_items++;
6682         it->parent->item->items =
6683           eina_list_prepend_relative(it->parent->item->items, EO_OBJ(it), eo_before);
6684         _item_expanded_set_noevent(it->parent, EINA_TRUE);
6685      }
6686    sd->items = eina_inlist_prepend_relative
6687        (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
6688 
6689    it->item->rel = before;
6690    before->item->rel_revs = eina_list_append(before->item->rel_revs, it);
6691    it->item->before = EINA_TRUE;
6692    _item_queue(sd, it, NULL);
6693 
6694    return EO_OBJ(it);
6695 }
6696 
6697 EOLIAN static Elm_Object_Item*
_elm_genlist_item_sorted_insert(Eo * obj,Elm_Genlist_Data * sd,const Elm_Genlist_Item_Class * itc,const void * data,Elm_Object_Item * eo_parent,Elm_Genlist_Item_Type type,Eina_Compare_Cb comp,Evas_Smart_Cb func,const void * func_data)6698 _elm_genlist_item_sorted_insert(Eo *obj, Elm_Genlist_Data *sd, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *eo_parent, Elm_Genlist_Item_Type type, Eina_Compare_Cb comp, Evas_Smart_Cb func, const void *func_data)
6699 {
6700    Elm_Object_Item *eo_rel = NULL;
6701    Elm_Gen_Item *rel = NULL;
6702    Elm_Gen_Item *it;
6703 
6704    EINA_SAFETY_ON_NULL_RETURN_VAL(comp, NULL);
6705    if (eo_parent)
6706      {
6707         ELM_GENLIST_ITEM_DATA_GET(eo_parent, parent);
6708         ELM_GENLIST_ITEM_CHECK_OR_RETURN(parent, NULL);
6709         EINA_SAFETY_ON_FALSE_RETURN_VAL((obj == WIDGET(parent)), NULL);
6710      }
6711 
6712    it = _elm_genlist_item_new
6713        (sd, itc, data, eo_parent, type, func, func_data);
6714    if (!it) return NULL;
6715    Elm_Object_Item *eo_it = EO_OBJ(it);
6716 
6717    sd->item_compare_cb = comp;
6718 
6719    if (it->parent)
6720      {
6721         Eina_List *l;
6722         int cmp_result;
6723 
6724         l = eina_list_search_sorted_near_list
6725             (it->parent->item->items, _elm_genlist_eo_item_list_compare, eo_it,
6726             &cmp_result);
6727 
6728         if (l)
6729           {
6730              eo_rel = eina_list_data_get(l);
6731              rel = efl_data_scope_get(eo_rel, ELM_GENLIST_ITEM_CLASS);
6732 
6733              if (cmp_result >= 0)
6734                {
6735                   it->parent->item->items = eina_list_prepend_relative_list
6736                       (it->parent->item->items, eo_it, l);
6737                   sd->items = eina_inlist_prepend_relative
6738                       (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
6739                   it->item->before = EINA_TRUE;
6740                }
6741              else // if (cmp_result < 0)
6742                {
6743                   it->parent->item->items = eina_list_append_relative_list
6744                       (it->parent->item->items, eo_it, l);
6745                   if (rel->item->items)
6746                     {
6747                        Eina_List *ll = _list_last_recursive(rel->item->items);
6748                        if (ll)
6749                          {
6750                             eo_rel = ll->data;
6751                             rel = efl_data_scope_get(eo_rel, ELM_GENLIST_ITEM_CLASS);
6752                          }
6753                     }
6754                   sd->items = eina_inlist_append_relative
6755                       (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
6756                   it->item->before = EINA_FALSE;
6757                }
6758           }
6759         else
6760           {
6761              // parent had no child
6762              rel = it->parent;
6763 
6764              it->parent->item->items = eina_list_prepend
6765                    (it->parent->item->items, eo_it);
6766              sd->items = eina_inlist_append_relative
6767                    (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
6768              it->item->before = EINA_FALSE;
6769              sd->top_level_parent_items++;
6770           }
6771 
6772         ELM_SAFE_FREE(sd->state, eina_inlist_sorted_state_free);
6773 
6774         // ensure expanded state is on
6775         _item_expanded_set_noevent(it->parent, EINA_TRUE);
6776      }
6777    else
6778      {
6779         if (!sd->state && !sd->top_level_parent_items)
6780           {
6781              sd->state = eina_inlist_sorted_state_new();
6782              eina_inlist_sorted_state_init(sd->state, sd->items);
6783              sd->requeued = EINA_FALSE;
6784           }
6785 
6786         if (it->item->type == ELM_GENLIST_ITEM_GROUP)
6787           sd->group_items = eina_list_append(sd->group_items, it);
6788 
6789         if (!sd->top_level_parent_items)
6790           {
6791              sd->items = eina_inlist_sorted_state_insert
6792                    (sd->items, EINA_INLIST_GET(it), _elm_genlist_item_compare,
6793                     sd->state);
6794 
6795              if (EINA_INLIST_GET(it)->next)
6796                {
6797                   rel = ELM_GEN_ITEM_NEXT(it);
6798                   it->item->before = EINA_TRUE;
6799                }
6800              else if (EINA_INLIST_GET(it)->prev)
6801                {
6802                   rel = ELM_GEN_ITEM_PREV(it);
6803                   it->item->before = EINA_FALSE;
6804                }
6805           }
6806         else
6807           {
6808              // Inlist is not sorted!
6809              Elm_Gen_Item *prev_rel = NULL;
6810              int cmp = 0;
6811 
6812              EINA_INLIST_FOREACH(sd->items, rel)
6813                {
6814                   cmp = comp(EO_OBJ(it), EO_OBJ(rel));
6815                   if (cmp < 0) break;
6816                   prev_rel = rel;
6817                   if (rel->item->items)
6818                     {
6819                        Eina_List *ll = _list_last_recursive(rel->item->items);
6820                        if (ll)
6821                          {
6822                             eo_rel = ll->data;
6823                             rel = efl_data_scope_get(eo_rel, ELM_GENLIST_ITEM_CLASS);
6824                          }
6825                     }
6826                   if (!EINA_INLIST_GET(rel)->next)
6827                     {
6828                        cmp = 1;
6829                        break;
6830                     }
6831                }
6832 
6833              if (!rel)
6834                {
6835                   sd->items = eina_inlist_prepend_relative(sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(prev_rel));
6836                   it->item->before = EINA_TRUE;
6837                   rel = prev_rel;
6838                }
6839              else if (cmp >= 0)
6840                {
6841                   sd->items = eina_inlist_append_relative(sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
6842                   it->item->before = EINA_FALSE;
6843                }
6844              else
6845                {
6846                   sd->items = eina_inlist_prepend_relative(sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
6847                   it->item->before = EINA_TRUE;
6848                }
6849           }
6850      }
6851 
6852    if (rel)
6853      {
6854         it->item->rel = rel;
6855         rel->item->rel_revs = eina_list_append(rel->item->rel_revs, it);
6856      }
6857 
6858    _item_queue(sd, it, _elm_genlist_item_list_compare);
6859 
6860    return eo_it;
6861 }
6862 
6863 EOLIAN static void
_elm_genlist_clear(Eo * obj,Elm_Genlist_Data * sd EINA_UNUSED)6864 _elm_genlist_clear(Eo *obj, Elm_Genlist_Data *sd EINA_UNUSED)
6865 {
6866    _internal_elm_genlist_clear(obj);
6867 }
6868 
6869 EOLIAN static void
_elm_genlist_multi_select_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool multi)6870 _elm_genlist_multi_select_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool multi)
6871 {
6872    sd->multi = !!multi;
6873 
6874    if (!sd->multi && sd->selected)
6875      {
6876         Eina_List *l, *ll;
6877         Elm_Object_Item *eo_it;
6878         Elm_Object_Item *last = sd->selected->data;
6879         EINA_LIST_FOREACH_SAFE(sd->selected, l, ll, eo_it)
6880           {
6881              if (last != eo_it)
6882                {
6883                   ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
6884                   _item_unselect(it);
6885                }
6886           }
6887      }
6888 }
6889 
6890 EOLIAN static Eina_Bool
_elm_genlist_multi_select_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)6891 _elm_genlist_multi_select_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
6892 {
6893    return sd->multi;
6894 }
6895 
6896 EOLIAN static void
_elm_genlist_multi_select_mode_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Elm_Object_Multi_Select_Mode mode)6897 _elm_genlist_multi_select_mode_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Elm_Object_Multi_Select_Mode mode)
6898 {
6899    if (mode >= ELM_OBJECT_MULTI_SELECT_MODE_MAX)
6900      return;
6901 
6902    if (sd->multi_select_mode != mode)
6903      sd->multi_select_mode = mode;
6904 }
6905 
6906 EOLIAN static Elm_Object_Multi_Select_Mode
_elm_genlist_multi_select_mode_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)6907 _elm_genlist_multi_select_mode_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
6908 {
6909    return sd->multi_select_mode;
6910 }
6911 
6912 EOLIAN static Elm_Object_Item*
_elm_genlist_selected_item_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)6913 _elm_genlist_selected_item_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
6914 {
6915    if (sd->selected)
6916       return sd->selected->data;
6917    else
6918       return NULL;
6919 }
6920 
6921 EOLIAN static const Eina_List*
_elm_genlist_selected_items_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)6922 _elm_genlist_selected_items_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
6923 {
6924    return sd->selected;
6925 }
6926 
6927 EOLIAN static Eina_List*
_elm_genlist_realized_items_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)6928 _elm_genlist_realized_items_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
6929 {
6930    Item_Block *itb;
6931    Eina_Bool done = EINA_FALSE;
6932 
6933    Eina_List *ret = NULL;
6934 
6935    EINA_INLIST_FOREACH(sd->blocks, itb)
6936      {
6937         if (itb->realized)
6938           {
6939              Eina_List *l;
6940              Elm_Gen_Item *it;
6941 
6942              done = EINA_TRUE;
6943              EINA_LIST_FOREACH(itb->items, l, it)
6944                {
6945                   if (it->realized) ret = eina_list_append(ret, EO_OBJ(it));
6946                }
6947           }
6948         else
6949           {
6950              if (done) break;
6951           }
6952      }
6953 
6954    return ret;
6955 }
6956 
6957 EOLIAN static Elm_Object_Item*
_elm_genlist_at_xy_item_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Evas_Coord x,Evas_Coord y,int * posret)6958 _elm_genlist_at_xy_item_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Evas_Coord x, Evas_Coord y, int *posret)
6959 {
6960    Evas_Coord ox, oy, ow, oh;
6961    Evas_Coord lasty;
6962    Item_Block *itb;
6963 
6964    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
6965    lasty = oy;
6966    EINA_INLIST_FOREACH(sd->blocks, itb)
6967      {
6968         Eina_List *l;
6969         Elm_Gen_Item *it;
6970 
6971         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->sd->pan_x,
6972                                  oy + itb->y - itb->sd->pan_y,
6973                                  itb->w, itb->h, x, y, 1, 1))
6974           continue;
6975         EINA_LIST_FOREACH(itb->items, l, it)
6976           {
6977              Evas_Coord itx, ity;
6978 
6979              itx = ox + itb->x + it->x - itb->sd->pan_x;
6980              ity = oy + itb->y + it->y - itb->sd->pan_y;
6981              if (ELM_RECTS_INTERSECT
6982                    (itx, ity, it->item->w, it->item->h, x, y, 1, 1))
6983                {
6984                   if (posret)
6985                     {
6986                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
6987                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
6988                          *posret = 1;
6989                        else *posret = 0;
6990                     }
6991 
6992                   return EO_OBJ(it);
6993                }
6994              lasty = ity + it->item->h;
6995           }
6996      }
6997    if (posret)
6998      {
6999         if (y > lasty) *posret = 1;
7000         else *posret = -1;
7001      }
7002 
7003    return NULL;
7004 }
7005 
7006 EOLIAN static Elm_Object_Item*
_elm_genlist_first_item_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)7007 _elm_genlist_first_item_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
7008 {
7009    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(sd->items);
7010 
7011    while (it && sd->filter && !_item_filtered_get(it, sd))
7012      it = ELM_GEN_ITEM_NEXT(it);
7013 
7014    return EO_OBJ(it);
7015 }
7016 
7017 EOLIAN static Elm_Object_Item*
_elm_genlist_last_item_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)7018 _elm_genlist_last_item_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
7019 {
7020    Elm_Gen_Item *it;
7021 
7022    if (!sd->items) return NULL;
7023    it = ELM_GEN_ITEM_FROM_INLIST(sd->items->last);
7024 
7025    while (it && sd->filter && !_item_filtered_get(it, sd))
7026      it = ELM_GEN_ITEM_PREV(it);
7027 
7028    return EO_OBJ(it);
7029 }
7030 
7031 EOLIAN static Elm_Object_Item *
_elm_genlist_item_next_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7032 _elm_genlist_item_next_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7033 {
7034    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
7035 
7036    do it = ELM_GEN_ITEM_NEXT(it);
7037    while (it && sd->filter && !_item_filtered_get(it, sd));
7038 
7039    return EO_OBJ(it);
7040 }
7041 
7042 EOLIAN static Elm_Object_Item *
_elm_genlist_item_prev_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7043 _elm_genlist_item_prev_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7044 {
7045    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
7046 
7047    do it = ELM_GEN_ITEM_PREV(it);
7048    while (it && sd->filter && !_item_filtered_get(it, sd));
7049 
7050    return EO_OBJ(it);
7051 }
7052 
7053 EOLIAN static Elm_Object_Item *
_elm_genlist_item_parent_item_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7054 _elm_genlist_item_parent_item_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7055 {
7056    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, NULL);
7057 
7058    return EO_OBJ(it->parent);
7059 }
7060 
7061 EOLIAN static unsigned int
_elm_genlist_item_subitems_count(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * item)7062 _elm_genlist_item_subitems_count(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *item)
7063 {
7064    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, 0);
7065 
7066    return eina_list_count(item->item->items);
7067 }
7068 
7069 EOLIAN static const Eina_List *
_elm_genlist_item_subitems_get(const Eo * eo_item EINA_UNUSED,Elm_Gen_Item * item)7070 _elm_genlist_item_subitems_get(const Eo *eo_item EINA_UNUSED, Elm_Gen_Item *item)
7071 {
7072    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, NULL);
7073 
7074    return item->item->items;
7075 }
7076 
7077 EOLIAN static void
_elm_genlist_item_subitems_clear(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it)7078 _elm_genlist_item_subitems_clear(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it)
7079 {
7080    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7081    ELM_GENLIST_DATA_GET(WIDGET(it), sd);
7082 
7083    if (!sd->tree_effect_enabled || !sd->move_effect_mode)
7084      _item_sub_items_clear(it);
7085    else
7086      {
7087         if (!_elm_genlist_tree_effect_setup(sd))
7088           _item_sub_items_clear(it);
7089      }
7090 }
7091 
7092 EOLIAN static void
_elm_genlist_item_selected_set(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it,Eina_Bool selected)7093 _elm_genlist_item_selected_set(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it,
7094       Eina_Bool selected)
7095 {
7096    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7097 
7098    if (elm_wdg_item_disabled_get(EO_OBJ(it))) return;
7099 
7100    selected = !!selected;
7101    if (it->selected == selected) return;
7102 
7103    if (selected) _item_select(it);
7104    else _item_unselect(it);
7105 }
7106 
7107 EOLIAN static Eina_Bool
_elm_genlist_item_selected_get(const Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it)7108 _elm_genlist_item_selected_get(const Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it)
7109 {
7110    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
7111 
7112    return it->selected;
7113 }
7114 
7115 static Elm_Gen_Item *
_elm_genlist_expanded_next_item_get(Elm_Gen_Item * it)7116 _elm_genlist_expanded_next_item_get(Elm_Gen_Item *it)
7117 {
7118    Elm_Object_Item *eo_it = EO_OBJ(it);
7119    Elm_Object_Item *eo_it2;
7120 
7121    if (it->item->expanded)
7122      {
7123         eo_it2 = elm_genlist_item_next_get(eo_it);
7124         ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
7125         return it2;
7126      }
7127    else
7128      {
7129         eo_it2 = elm_genlist_item_next_get(eo_it);
7130         while (eo_it2)
7131           {
7132              ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
7133              if (it->item->expanded_depth >= it2->item->expanded_depth) return it2;
7134              eo_it2 = elm_genlist_item_next_get(eo_it2);
7135           }
7136      }
7137    return efl_data_scope_get(eo_it2, ELM_GENLIST_ITEM_CLASS);
7138 }
7139 
7140 static void
_elm_genlist_move_items_set(Elm_Gen_Item * it,Eina_Bool expanded)7141 _elm_genlist_move_items_set(Elm_Gen_Item *it, Eina_Bool expanded)
7142 {
7143    Eina_List *l, *ll;
7144    Elm_Gen_Item *it2 = NULL;
7145    Evas_Coord ox, oy, ow, oh, dh = 0;
7146    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
7147 
7148    sd->expanded_next_item =
7149      _elm_genlist_expanded_next_item_get(it);
7150 
7151    if (expanded)
7152      {
7153         Elm_Object_Item *eo_item;
7154         l = elm_genlist_realized_items_get((sd)->obj);
7155         EINA_LIST_FREE(l, eo_item)
7156           {
7157              ELM_GENLIST_ITEM_DATA_GET(eo_item, item);
7158              sd->move_items = eina_list_append(sd->move_items, item);
7159           }
7160 
7161         EINA_LIST_FOREACH_SAFE(sd->move_items, l, ll, it2)
7162           {
7163              if (it2 == sd->expanded_next_item) break;
7164              sd->move_items = eina_list_remove(sd->move_items, it2);
7165           }
7166      }
7167    else
7168      {
7169         Elm_Object_Item *eo_it2 = NULL;
7170         evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7171         if (sd->expanded_next_item) eo_it2 = EO_OBJ(sd->expanded_next_item);
7172 
7173         while (eo_it2 && (dh < oy + oh))
7174           {
7175              it2 = efl_data_scope_get(eo_it2, ELM_GENLIST_ITEM_CLASS);
7176              dh += it2->item->h;
7177              sd->move_items = eina_list_append(sd->move_items, it2);
7178              eo_it2 = elm_genlist_item_next_get(eo_it2);
7179           }
7180      }
7181 }
7182 
7183 static void
_event_block_rect_update(const Evas_Object * obj)7184 _event_block_rect_update(const Evas_Object *obj)
7185 {
7186    Evas_Coord ox, oy, ow, oh;
7187 
7188    ELM_GENLIST_CHECK(obj);
7189    ELM_GENLIST_DATA_GET(obj, sd);
7190 
7191    if (!sd->event_block_rect)
7192      {
7193         sd->event_block_rect = evas_object_rectangle_add(
7194            evas_object_evas_get(sd->obj));
7195         evas_object_smart_member_add(sd->event_block_rect, sd->pan_obj);
7196         evas_object_color_set(sd->event_block_rect, 0, 0, 0, 0);
7197      }
7198 
7199    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
7200    efl_gfx_entity_geometry_set(sd->pan_obj, EINA_RECT(ox, oy, ow, oh));
7201 }
7202 
7203 static void
_item_expanded_set_noevent(Elm_Gen_Item * it,Eina_Bool expanded)7204 _item_expanded_set_noevent(Elm_Gen_Item *it, Eina_Bool expanded)
7205 {
7206    EINA_SAFETY_ON_NULL_RETURN(it);
7207 
7208    if (it->item->expanded == expanded) return;
7209    it->item->expanded = expanded;
7210    if (expanded)
7211      {
7212         if (it->realized)
7213           edje_object_signal_emit(VIEW(it), SIGNAL_EXPANDED, "elm");
7214      }
7215    else
7216      {
7217         if (it->realized)
7218           edje_object_signal_emit(VIEW(it), SIGNAL_CONTRACTED, "elm");
7219      }
7220 }
7221 
7222 EOLIAN static void
_elm_genlist_item_expanded_set(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it,Eina_Bool expanded)7223 _elm_genlist_item_expanded_set(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it, Eina_Bool expanded)
7224 {
7225    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7226    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
7227 
7228    expanded = !!expanded;
7229    if (it->item->expanded == expanded) return;
7230    if (it->item->type != ELM_GENLIST_ITEM_TREE) return;
7231    sd->expanded_item = it;
7232    _elm_genlist_move_items_set(it, expanded);
7233 
7234    if (sd->tree_effect_enabled)
7235      _event_block_rect_update(WIDGET(it));
7236 
7237    if (expanded)
7238      {
7239         sd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_EXPAND;
7240         _item_expanded_set_noevent(it, EINA_TRUE);
7241         efl_event_callback_legacy_call
7242               (WIDGET(it), ELM_GENLIST_EVENT_EXPANDED, EO_OBJ(it));
7243         sd->auto_scroll_enabled = EINA_TRUE;
7244         if (_elm_config->atspi_mode)
7245           efl_access_state_changed_signal_emit(eo_item, EFL_ACCESS_STATE_TYPE_EXPANDED, EINA_TRUE);
7246      }
7247    else
7248      {
7249         sd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_CONTRACT;
7250         _item_expanded_set_noevent(it, EINA_FALSE);
7251         efl_event_callback_legacy_call
7252               (WIDGET(it), ELM_GENLIST_EVENT_CONTRACTED, EO_OBJ(it));
7253         sd->auto_scroll_enabled = EINA_FALSE;
7254         if (_elm_config->atspi_mode)
7255           efl_access_state_changed_signal_emit(eo_item, EFL_ACCESS_STATE_TYPE_EXPANDED, EINA_FALSE);
7256      }
7257 }
7258 
7259 EOLIAN static Eina_Bool
_elm_genlist_item_expanded_get(const Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it)7260 _elm_genlist_item_expanded_get(const Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it)
7261 {
7262    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
7263 
7264    return it->item->expanded;
7265 }
7266 
7267 EOLIAN static int
_elm_genlist_item_expanded_depth_get(const Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it)7268 _elm_genlist_item_expanded_depth_get(const Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it)
7269 {
7270    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, 0);
7271 
7272    return it->item->expanded_depth;
7273 }
7274 
7275 static Eina_Bool
_elm_genlist_item_coordinates_calc(Elm_Gen_Item * it,Elm_Genlist_Item_Scrollto_Type type,Eina_Bool bring_in,Evas_Coord * x,Evas_Coord * y,Evas_Coord * w,Evas_Coord * h)7276 _elm_genlist_item_coordinates_calc(Elm_Gen_Item *it,
7277                                    Elm_Genlist_Item_Scrollto_Type type,
7278                                    Eina_Bool bring_in,
7279                                    Evas_Coord *x,
7280                                    Evas_Coord *y,
7281                                    Evas_Coord *w,
7282                                    Evas_Coord *h)
7283 {
7284    Evas_Coord gith = 0;
7285    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
7286 
7287    Eina_Bool deferred_show = EINA_FALSE;
7288 
7289    switch (type)
7290      {
7291       case ELM_GENLIST_ITEM_SCROLLTO_IN:
7292       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
7293       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
7294       case ELM_GENLIST_ITEM_SCROLLTO_BOTTOM:
7295          break;
7296       default: /* Filters unsupported type */
7297          return EINA_FALSE;
7298      }
7299 
7300    //Can't goto the item right now. Reserve it instead.
7301    if (sd->queue || !(sd->homogeneous && (sd->mode == ELM_LIST_COMPRESS)))
7302      {
7303         if ((it->item->queued) || (!it->item->mincalcd) || (sd->queue))
7304           deferred_show = EINA_TRUE;
7305      }
7306    if ((it->item->block) && (it->item->block->w < 1)) deferred_show = EINA_TRUE;
7307 
7308    evas_object_geometry_get(sd->pan_obj, NULL, NULL, w, h);
7309    if (*w < 1 || *h < 1) deferred_show = EINA_TRUE;
7310 
7311    if (deferred_show)
7312      {
7313         sd->check_scroll = EINA_TRUE;
7314         sd->show_item = it;
7315         sd->bring_in = bring_in;
7316         sd->scroll_to_type = type;
7317         it->item->show_me = EINA_TRUE;
7318 
7319         efl_canvas_group_change(sd->obj);
7320 
7321         return EINA_FALSE;
7322      }
7323 
7324    if (sd->show_item)
7325      {
7326         sd->show_item->item->show_me = EINA_FALSE;
7327         sd->show_item = NULL;
7328      }
7329 
7330    switch (type)
7331      {
7332       case ELM_GENLIST_ITEM_SCROLLTO_IN:
7333         if ((it->item->group_item) &&
7334             (sd->pan_y > (it->y + it->item->block->y)))
7335           gith = it->item->group_item->item->h;
7336         *h = it->item->h;
7337         *y = it->y + it->item->block->y - gith;
7338         break;
7339 
7340       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
7341         if (it->item->group_item) gith = it->item->group_item->item->h;
7342         *y = it->y + it->item->block->y - gith;
7343         break;
7344 
7345       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
7346         *y = it->y + it->item->block->y - (*h / 2) + (it->item->h / 2);
7347         break;
7348 
7349       case ELM_GENLIST_ITEM_SCROLLTO_BOTTOM:
7350         *y = it->y + it->item->block->y - *h + it->item->h;
7351         break;
7352 
7353       default:
7354         return EINA_FALSE;
7355      }
7356 
7357    *x = it->x + it->item->block->x;
7358    *w = it->item->block->w;
7359 
7360    return EINA_TRUE;
7361 }
7362 
7363 EOLIAN static void
_elm_genlist_item_promote(Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7364 _elm_genlist_item_promote(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7365 {
7366    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7367 
7368    Elm_Object_Item *eo_first_item = elm_genlist_first_item_get(WIDGET(it));
7369    ELM_GENLIST_ITEM_DATA_GET(eo_first_item, first_item);
7370    _item_move_before(it, first_item);
7371 }
7372 
7373 EOLIAN static void
_elm_genlist_item_demote(Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7374 _elm_genlist_item_demote(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7375 {
7376    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7377    Elm_Object_Item *eo_last_item = elm_genlist_last_item_get(WIDGET(it));
7378    ELM_GENLIST_ITEM_DATA_GET(eo_last_item, last_item);
7379    _item_move_after(it, last_item);
7380 }
7381 
7382 EOLIAN static void
_elm_genlist_item_show(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * item,Elm_Genlist_Item_Scrollto_Type type)7383 _elm_genlist_item_show(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *item, Elm_Genlist_Item_Scrollto_Type type)
7384 {
7385    Evas_Coord x, y, w, h;
7386 
7387    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
7388 
7389    if (_elm_genlist_item_coordinates_calc
7390          (item, type, EINA_FALSE, &x, &y, &w, &h))
7391       elm_interface_scrollable_content_region_show
7392             (WIDGET(item), x, y, w, h);
7393 }
7394 
7395 EOLIAN static void
_elm_genlist_item_bring_in(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * item,Elm_Genlist_Item_Scrollto_Type type)7396 _elm_genlist_item_bring_in(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *item, Elm_Genlist_Item_Scrollto_Type type)
7397 {
7398    Evas_Coord x, y, w, h;
7399 
7400    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
7401 
7402    if (_elm_genlist_item_coordinates_calc
7403          (item, type, EINA_TRUE, &x, &y, &w, &h))
7404       elm_interface_scrollable_region_bring_in(WIDGET(item), x, y, w, h);
7405 }
7406 
7407 EOLIAN static void
_elm_genlist_item_all_contents_unset(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it,Eina_List ** l)7408 _elm_genlist_item_all_contents_unset(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it, Eina_List **l)
7409 {
7410    Evas_Object *content;
7411 
7412    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7413 
7414    EINA_LIST_FREE(it->contents, content)
7415      {
7416         _elm_widget_sub_object_redirect_to_top(WIDGET(it), content);
7417         edje_object_part_unswallow(VIEW(it), content);
7418         evas_object_hide(content);
7419         if (l) *l = eina_list_append(*l, content);
7420      }
7421 }
7422 
7423 static void
_mark_item_update(Elm_Gen_Item * it)7424 _mark_item_update(Elm_Gen_Item *it)
7425 {
7426    it->item->mincalcd = EINA_FALSE;
7427    it->item->updateme = EINA_TRUE;
7428    it->item->block->updateme = EINA_TRUE;
7429 }
7430 
7431 EOLIAN static void
_elm_genlist_item_update(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it)7432 _elm_genlist_item_update(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it)
7433 {
7434    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7435    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
7436 
7437    if (!it->item->block) return;
7438    _mark_item_update(it);
7439    ecore_job_del(sd->update_job);
7440    sd->update_job = ecore_job_add(_update_job, sd->obj);
7441 }
7442 
7443 EOLIAN static void
_elm_genlist_item_fields_update(Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it,const char * parts,Elm_Genlist_Item_Field_Type itf)7444 _elm_genlist_item_fields_update(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it,
7445                                const char *parts,
7446                                Elm_Genlist_Item_Field_Type itf)
7447 {
7448    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7449 
7450    if (!it->item->block) return;
7451 
7452    if (!it->realized)
7453      {
7454         if (!itf || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
7455           elm_genlist_item_update(eo_item);
7456         return;
7457      }
7458 
7459    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT))
7460      {
7461         _item_text_realize(it, VIEW(it), &it->texts, parts);
7462      }
7463    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
7464      {
7465         _item_content_realize(it, VIEW(it), &it->contents, "contents", parts, EINA_FALSE);
7466         if (it->flipped)
7467           {
7468              _item_content_realize(it, VIEW(it), &it->item->flip_contents,
7469                                    "flips", parts, EINA_FALSE);
7470           }
7471         if (it->item->deco_it_view)
7472           {
7473              _item_content_realize(it, it->item->deco_it_view,
7474                                    &it->item->deco_it_contents,
7475                                    "contents", parts, EINA_FALSE);
7476           }
7477         if (it->item->wsd->decorate_all_mode)
7478           {
7479              _item_content_realize(it, it->deco_all_view,
7480                                    &it->item->deco_all_contents,
7481                                    "contents", parts, EINA_FALSE);
7482           }
7483         if (it->has_contents != (!!it->contents))
7484           it->item->mincalcd = EINA_FALSE;
7485         it->has_contents = !!it->contents;
7486         if (it->item->type == ELM_GENLIST_ITEM_NONE)
7487           {
7488              Evas_Object* eobj;
7489              Eina_List* l;
7490              it->item_focus_chain = eina_list_free(it->item_focus_chain);
7491              EINA_LIST_FOREACH(it->contents, l, eobj)
7492                if (elm_widget_is(eobj) && elm_object_focus_allow_get(eobj))
7493                  it->item_focus_chain = eina_list_append(it->item_focus_chain, eobj);
7494           }
7495      }
7496 
7497    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
7498      _item_state_realize(it, VIEW(it), parts);
7499 
7500    if (!it->item->mincalcd)
7501      elm_genlist_item_update(eo_item);
7502 }
7503 
7504 EOLIAN static void
_elm_genlist_item_item_class_update(Eo * eo_it,Elm_Gen_Item * it,const Elm_Genlist_Item_Class * itc)7505 _elm_genlist_item_item_class_update(Eo *eo_it, Elm_Gen_Item *it,
7506                                    const Elm_Genlist_Item_Class *itc)
7507 {
7508    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7509    EINA_SAFETY_ON_NULL_RETURN(itc);
7510 
7511    /* Decrease the orignal item class refcount to prevent memory leak */
7512    if (it->itc != itc)
7513      {
7514         elm_genlist_item_class_unref((Elm_Genlist_Item_Class *)it->itc);
7515         it->itc = itc;
7516         elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)it->itc);
7517      }
7518 
7519    if (!it->item->block) return;
7520    it->item->nocache_once = EINA_TRUE;
7521 
7522    ELM_SAFE_FREE(it->texts, elm_widget_stringlist_free);
7523    ELM_SAFE_FREE(it->item->deco_it_texts, elm_widget_stringlist_free);
7524    ELM_SAFE_FREE(it->item->deco_all_texts, elm_widget_stringlist_free);
7525 
7526    elm_genlist_item_update(eo_it);
7527 }
7528 
7529 EOLIAN static const Elm_Genlist_Item_Class *
_elm_genlist_item_item_class_get(const Eo * eo_item EINA_UNUSED,Elm_Gen_Item * it)7530 _elm_genlist_item_item_class_get(const Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it)
7531 {
7532    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, NULL);
7533 
7534    return it->itc;
7535 }
7536 
7537 static Evas_Object *
_elm_genlist_item_label_create(void * data,Evas_Object * obj EINA_UNUSED,Evas_Object * tooltip,void * it EINA_UNUSED)7538 _elm_genlist_item_label_create(void *data,
7539                                Evas_Object *obj EINA_UNUSED,
7540                                Evas_Object *tooltip,
7541                                void *it EINA_UNUSED)
7542 {
7543    Evas_Object *label = elm_label_add(tooltip);
7544 
7545    if (!label)
7546      return NULL;
7547 
7548    elm_object_style_set(label, "tooltip");
7549    elm_object_text_set(label, data);
7550 
7551    return label;
7552 }
7553 
7554 static void
_elm_genlist_item_label_del_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)7555 _elm_genlist_item_label_del_cb(void *data,
7556                                Evas_Object *obj EINA_UNUSED,
7557                                void *event_info EINA_UNUSED)
7558 {
7559    eina_stringshare_del(data);
7560 }
7561 
7562 EAPI void
elm_genlist_item_tooltip_text_set(Elm_Object_Item * it,const char * text)7563 elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
7564                                   const char *text)
7565 {
7566    elm_wdg_item_tooltip_text_set(it, text);
7567 }
7568 
7569 EOLIAN static void
_elm_genlist_item_elm_widget_item_tooltip_text_set(Eo * eo_it,Elm_Gen_Item * it,const char * text)7570 _elm_genlist_item_elm_widget_item_tooltip_text_set(Eo *eo_it, Elm_Gen_Item *it, const char *text)
7571 {
7572    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7573 
7574    text = eina_stringshare_add(text);
7575    elm_genlist_item_tooltip_content_cb_set
7576      (eo_it, _elm_genlist_item_label_create, text,
7577      _elm_genlist_item_label_del_cb);
7578 }
7579 
7580 EAPI void
elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item * item,Elm_Tooltip_Item_Content_Cb func,const void * data,Evas_Smart_Cb del_cb)7581 elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item *item,
7582                                         Elm_Tooltip_Item_Content_Cb func,
7583                                         const void *data,
7584                                         Evas_Smart_Cb del_cb)
7585 {
7586    elm_wdg_item_tooltip_content_cb_set(item, func, data, del_cb);
7587 }
7588 
7589 EOLIAN static void
_elm_genlist_item_elm_widget_item_tooltip_content_cb_set(Eo * eo_it,Elm_Gen_Item * it,Elm_Tooltip_Item_Content_Cb func,const void * data,Evas_Smart_Cb del_cb)7590 _elm_genlist_item_elm_widget_item_tooltip_content_cb_set(Eo *eo_it, Elm_Gen_Item *it,
7591                                         Elm_Tooltip_Item_Content_Cb func,
7592                                         const void *data,
7593                                         Evas_Smart_Cb del_cb)
7594 {
7595    ELM_GENLIST_ITEM_CHECK_OR_GOTO(it, error);
7596 
7597    if ((it->tooltip.content_cb != func) || (it->tooltip.data != data))
7598      {
7599         if (it->tooltip.del_cb)
7600            it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
7601 
7602         it->tooltip.content_cb = func;
7603         it->tooltip.data = data;
7604         it->tooltip.del_cb = del_cb;
7605      }
7606 
7607    if (VIEW(it))
7608      {
7609         elm_wdg_item_tooltip_content_cb_set
7610               (efl_super(eo_it, ELM_GENLIST_ITEM_CLASS), it->tooltip.content_cb, it->tooltip.data, NULL);
7611         elm_wdg_item_tooltip_style_set(eo_it, it->tooltip.style);
7612         elm_wdg_item_tooltip_window_mode_set(eo_it, it->tooltip.free_size);
7613      }
7614 
7615    return;
7616 
7617 error:
7618    if (del_cb) del_cb((void *)data, NULL, NULL);
7619 }
7620 
7621 EAPI void
elm_genlist_item_tooltip_unset(Elm_Object_Item * item)7622 elm_genlist_item_tooltip_unset(Elm_Object_Item *item)
7623 {
7624    elm_wdg_item_tooltip_unset(item);
7625 }
7626 
7627 EOLIAN static void
_elm_genlist_item_elm_widget_item_tooltip_unset(Eo * eo_it,Elm_Gen_Item * it)7628 _elm_genlist_item_elm_widget_item_tooltip_unset(Eo *eo_it, Elm_Gen_Item *it)
7629 {
7630    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7631 
7632    if ((VIEW(it)) && (it->tooltip.content_cb))
7633      elm_wdg_item_tooltip_unset(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS));
7634 
7635    if (it->tooltip.del_cb)
7636      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
7637    it->tooltip.del_cb = NULL;
7638    it->tooltip.content_cb = NULL;
7639    it->tooltip.data = NULL;
7640    it->tooltip.free_size = EINA_FALSE;
7641    if (it->tooltip.style)
7642      elm_wdg_item_tooltip_style_set(eo_it, NULL);
7643 }
7644 
7645 EAPI void
elm_genlist_item_tooltip_style_set(Elm_Object_Item * item,const char * style)7646 elm_genlist_item_tooltip_style_set(Elm_Object_Item *item,
7647                                    const char *style)
7648 {
7649    elm_wdg_item_tooltip_style_set(item, style);
7650 }
7651 
7652 EOLIAN static void
_elm_genlist_item_elm_widget_item_tooltip_style_set(Eo * eo_it,Elm_Gen_Item * it,const char * style)7653 _elm_genlist_item_elm_widget_item_tooltip_style_set(Eo *eo_it, Elm_Gen_Item *it,
7654                                    const char *style)
7655 {
7656    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7657 
7658    eina_stringshare_replace(&it->tooltip.style, style);
7659    if (VIEW(it)) elm_wdg_item_tooltip_style_set(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS), style);
7660 }
7661 
7662 EAPI const char *
elm_genlist_item_tooltip_style_get(const Elm_Object_Item * it)7663 elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
7664 {
7665    return elm_wdg_item_tooltip_style_get(it);
7666 }
7667 
7668 EOLIAN static const char *
_elm_genlist_item_elm_widget_item_tooltip_style_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7669 _elm_genlist_item_elm_widget_item_tooltip_style_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7670 {
7671    return it->tooltip.style;
7672 }
7673 
7674 EAPI Eina_Bool
elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item * item,Eina_Bool disable)7675 elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *item,
7676                                          Eina_Bool disable)
7677 {
7678    return elm_wdg_item_tooltip_window_mode_set(item, disable);
7679 }
7680 
7681 EOLIAN static Eina_Bool
_elm_genlist_item_elm_widget_item_tooltip_window_mode_set(Eo * eo_it,Elm_Gen_Item * it,Eina_Bool disable)7682 _elm_genlist_item_elm_widget_item_tooltip_window_mode_set(Eo *eo_it, Elm_Gen_Item *it,
7683                                    Eina_Bool disable)
7684 {
7685    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
7686 
7687    it->tooltip.free_size = disable;
7688    if (VIEW(it))
7689      {
7690         Eina_Bool ret;
7691         ret = elm_wdg_item_tooltip_window_mode_set(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS), disable);
7692         return ret;
7693      }
7694 
7695    return disable;
7696 }
7697 
7698 EAPI Eina_Bool
elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item * eo_it)7699 elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *eo_it)
7700 {
7701    return elm_wdg_item_tooltip_window_mode_get(eo_it);
7702 }
7703 
7704 EOLIAN static Eina_Bool
_elm_genlist_item_elm_widget_item_tooltip_window_mode_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7705 _elm_genlist_item_elm_widget_item_tooltip_window_mode_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7706 {
7707    return it->tooltip.free_size;
7708 }
7709 
7710 EAPI void
elm_genlist_item_cursor_set(Elm_Object_Item * item,const char * cursor)7711 elm_genlist_item_cursor_set(Elm_Object_Item *item,
7712                             const char *cursor)
7713 {
7714    elm_wdg_item_cursor_set(item, cursor);
7715 }
7716 
7717 EOLIAN static void
_elm_genlist_item_elm_widget_item_cursor_set(Eo * eo_it,Elm_Gen_Item * it,const char * cursor)7718 _elm_genlist_item_elm_widget_item_cursor_set(Eo *eo_it, Elm_Gen_Item *it,
7719                             const char *cursor)
7720 {
7721    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7722    eina_stringshare_replace(&it->mouse_cursor, cursor);
7723    if (VIEW(it)) elm_wdg_item_cursor_set(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS), cursor);
7724 }
7725 
7726 EAPI const char *
elm_genlist_item_cursor_get(const Elm_Object_Item * eo_it)7727 elm_genlist_item_cursor_get(const Elm_Object_Item *eo_it)
7728 {
7729    return elm_wdg_item_cursor_get(eo_it);
7730 }
7731 
7732 EAPI void
elm_genlist_item_cursor_unset(Elm_Object_Item * item)7733 elm_genlist_item_cursor_unset(Elm_Object_Item *item)
7734 {
7735    elm_wdg_item_cursor_unset(item);
7736 }
7737 
7738 EOLIAN static void
_elm_genlist_item_elm_widget_item_cursor_unset(Eo * eo_it,Elm_Gen_Item * it)7739 _elm_genlist_item_elm_widget_item_cursor_unset(Eo *eo_it, Elm_Gen_Item *it)
7740 {
7741    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
7742 
7743    if (!it->mouse_cursor) return;
7744 
7745    if (VIEW(it)) elm_wdg_item_cursor_unset(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS));
7746 
7747    ELM_SAFE_FREE(it->mouse_cursor, eina_stringshare_del);
7748 }
7749 
7750 EAPI void
elm_genlist_item_cursor_style_set(Elm_Object_Item * eo_it,const char * style)7751 elm_genlist_item_cursor_style_set(Elm_Object_Item *eo_it,
7752                                   const char *style)
7753 {
7754    elm_wdg_item_cursor_style_set(eo_it, style);
7755 }
7756 
7757 EAPI const char *
elm_genlist_item_cursor_style_get(const Elm_Object_Item * eo_it)7758 elm_genlist_item_cursor_style_get(const Elm_Object_Item *eo_it)
7759 {
7760    return elm_wdg_item_cursor_style_get(eo_it);
7761 }
7762 
7763 EAPI void
elm_genlist_item_cursor_engine_only_set(Elm_Object_Item * eo_it,Eina_Bool engine_only)7764 elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *eo_it,
7765                                         Eina_Bool engine_only)
7766 {
7767    elm_wdg_item_cursor_engine_only_set(eo_it, engine_only);
7768 }
7769 
7770 EAPI Eina_Bool
elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item * eo_it)7771 elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *eo_it)
7772 {
7773    return elm_wdg_item_cursor_engine_only_get(eo_it);
7774 }
7775 
7776 EOLIAN static int
_elm_genlist_item_index_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)7777 _elm_genlist_item_index_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
7778 {
7779    int cnt = 1;
7780    Elm_Gen_Item *tmp;
7781    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, -1);
7782 
7783    EINA_INLIST_FOREACH(it->item->wsd->items, tmp)
7784     {
7785        if (tmp == it) break;
7786        cnt++;
7787     }
7788    return cnt;
7789 }
7790 
7791 EOLIAN static void
_elm_genlist_mode_set(Eo * obj,Elm_Genlist_Data * sd,Elm_List_Mode mode)7792 _elm_genlist_mode_set(Eo *obj, Elm_Genlist_Data *sd, Elm_List_Mode mode)
7793 {
7794    if (sd->mode == mode) return;
7795    sd->mode = mode;
7796 
7797    if (sd->mode == ELM_LIST_LIMIT)
7798      {
7799         sd->scr_minw = EINA_TRUE;
7800         sd->scr_minh = EINA_FALSE;
7801      }
7802    else if (sd->mode == ELM_LIST_EXPAND)
7803      {
7804         sd->scr_minw = EINA_TRUE;
7805         sd->scr_minh = EINA_TRUE;
7806      }
7807    else
7808      {
7809         sd->scr_minw = EINA_FALSE;
7810         sd->scr_minh = EINA_FALSE;
7811      }
7812 
7813    elm_layout_sizing_eval(obj);
7814 }
7815 
7816 EOLIAN static Elm_List_Mode
_elm_genlist_mode_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)7817 _elm_genlist_mode_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
7818 {
7819    return sd->mode;
7820 }
7821 
7822 EAPI void
elm_genlist_bounce_set(Evas_Object * obj,Eina_Bool h_bounce,Eina_Bool v_bounce)7823 elm_genlist_bounce_set(Evas_Object *obj,
7824                        Eina_Bool h_bounce,
7825                        Eina_Bool v_bounce)
7826 {
7827    ELM_GENLIST_CHECK(obj);
7828    elm_interface_scrollable_bounce_allow_set(obj, h_bounce, v_bounce);
7829 }
7830 
7831 EOLIAN static void
_elm_genlist_elm_interface_scrollable_bounce_allow_set(Eo * obj,Elm_Genlist_Data * sd,Eina_Bool h_bounce,Eina_Bool v_bounce)7832 _elm_genlist_elm_interface_scrollable_bounce_allow_set(Eo *obj, Elm_Genlist_Data *sd, Eina_Bool h_bounce, Eina_Bool v_bounce)
7833 {
7834    sd->h_bounce = !!h_bounce;
7835    sd->v_bounce = !!v_bounce;
7836    elm_interface_scrollable_bounce_allow_set
7837          (efl_super(obj, MY_CLASS), sd->h_bounce, sd->v_bounce);
7838 }
7839 
7840 EAPI void
elm_genlist_bounce_get(const Evas_Object * obj,Eina_Bool * h_bounce,Eina_Bool * v_bounce)7841 elm_genlist_bounce_get(const Evas_Object *obj,
7842                        Eina_Bool *h_bounce,
7843                        Eina_Bool *v_bounce)
7844 {
7845    ELM_GENLIST_CHECK(obj);
7846    elm_interface_scrollable_bounce_allow_get
7847          (obj, h_bounce, v_bounce);
7848 }
7849 
7850 EOLIAN static void
_elm_genlist_elm_interface_scrollable_bounce_allow_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool * h_bounce,Eina_Bool * v_bounce)7851 _elm_genlist_elm_interface_scrollable_bounce_allow_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
7852 {
7853    if (h_bounce) *h_bounce = sd->h_bounce;
7854    if (v_bounce) *v_bounce = sd->v_bounce;
7855 }
7856 
7857 EOLIAN static void
_elm_genlist_homogeneous_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool homogeneous)7858 _elm_genlist_homogeneous_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool homogeneous)
7859 {
7860    sd->homogeneous = !!homogeneous;
7861 }
7862 
7863 EOLIAN static Eina_Bool
_elm_genlist_homogeneous_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)7864 _elm_genlist_homogeneous_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
7865 {
7866    return sd->homogeneous;
7867 }
7868 
7869 EOLIAN static void
_elm_genlist_block_count_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,int count)7870 _elm_genlist_block_count_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, int count)
7871 {
7872    EINA_SAFETY_ON_TRUE_RETURN(count < 1);
7873 
7874    sd->max_items_per_block = count;
7875    sd->item_cache_max = sd->max_items_per_block * 2;
7876    _item_cache_clean(sd);
7877 }
7878 
7879 EOLIAN static int
_elm_genlist_block_count_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)7880 _elm_genlist_block_count_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
7881 {
7882    return sd->max_items_per_block;
7883 }
7884 
7885 static void
_filter_item_internal(Elm_Gen_Item * it)7886 _filter_item_internal(Elm_Gen_Item *it)
7887 {
7888    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
7889    if (sd->filter_data)
7890      {
7891         if ((it->parent && !_item_filtered_get(it->parent, sd)) ||
7892             (it->itc->func.filter_get &&
7893              !it->itc->func.filter_get(
7894                 (void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)),
7895                 WIDGET(it), sd->filter_data)))
7896           {
7897              it->hide = EINA_TRUE;
7898              if (it->item->block)
7899                it->item->block->changed = EINA_TRUE;
7900           }
7901         else
7902           sd->filtered_count++;
7903      }
7904    it->filtered = EINA_TRUE;
7905    sd->processed_count++;
7906 }
7907 
7908 // Returns true if the item is not filtered out, but remains visible.
7909 static Eina_Bool
_item_filtered_get(Elm_Gen_Item * it,Elm_Genlist_Data * sd)7910 _item_filtered_get(Elm_Gen_Item *it, Elm_Genlist_Data *sd)
7911 {
7912    Eina_List *l;
7913    /* no filter exists: item will always be visible */
7914    if (!sd->filter_data) return EINA_TRUE;
7915    if (!it->filtered)
7916      {
7917         l = eina_list_data_find_list(sd->filter_queue, it);
7918         if (l)
7919           sd->filter_queue = eina_list_remove_list(sd->filter_queue, l);
7920         if (it->item->queued)
7921           l = eina_list_data_find_list(sd->queue, it);
7922         else
7923           l = NULL;
7924         if (l)
7925           {
7926              sd->queue = eina_list_remove_list(sd->queue, l);
7927              it->item->queued = EINA_FALSE;
7928              _item_process(sd, it);
7929              _item_process_post(sd, it);
7930           }
7931 
7932         _filter_item_internal(it);
7933         if (it->item->block)
7934           it->item->block->changed = EINA_TRUE;
7935         efl_canvas_group_change(sd->obj);
7936         sd->need_calc = EINA_TRUE;
7937    }
7938    return !it->hide;
7939 }
7940 
7941 static int
_filter_queue_process(Elm_Genlist_Data * sd)7942 _filter_queue_process(Elm_Genlist_Data *sd)
7943 {
7944    int n;
7945    Elm_Gen_Item *it;
7946    double t0;
7947 
7948    t0 = ecore_time_get();
7949    for (n = 0; ((sd->filter_queue) && (sd->processed_count < ITEM_QUEUE_MAX)); n++)
7950      {
7951         it = eina_list_data_get(sd->filter_queue);
7952         if (!it) break;
7953         //FIXME: This is added as a fail safe code for items not yet processed.
7954         if (it->item->queued)
7955           {
7956              sd->filter_queue = eina_list_remove_list
7957                               (sd->filter_queue, sd->filter_queue);
7958              sd->filter_queue = eina_list_append(sd->filter_queue, it);
7959              it = eina_list_data_get(sd->filter_queue);
7960           }
7961         sd->filter_queue = eina_list_remove_list(sd->filter_queue, sd->filter_queue);
7962         _filter_item_internal(it);
7963         it->item->block->changed = EINA_TRUE;
7964         if ((ecore_time_get() - t0) > (ecore_animator_frametime_get()))
7965           {
7966              //At least 1 item is filtered by this time, so return n+1 for first loop
7967              n++;
7968              break;
7969           }
7970      }
7971    return n;
7972 }
7973 
7974 static Eina_Bool
_filter_process(void * data,Eina_Bool * wakeup)7975 _filter_process(void *data,
7976               Eina_Bool *wakeup)
7977 {
7978    Elm_Genlist_Data *sd = data;
7979 
7980    if (_filter_queue_process(sd) > 0) *wakeup = EINA_TRUE;
7981    if (!sd->filter_queue) return ECORE_CALLBACK_CANCEL;
7982    return ECORE_CALLBACK_RENEW;
7983 }
7984 
7985 static Eina_Bool
_item_filter_enterer(void * data)7986 _item_filter_enterer(void *data)
7987 {
7988    Eina_Bool wakeup = EINA_FALSE;
7989    ELM_GENLIST_DATA_GET(data, sd);
7990    Eina_Bool ok = _filter_process(sd, &wakeup);
7991    if (wakeup)
7992      {
7993         // wake up mainloop
7994         efl_canvas_group_change(sd->obj);
7995      }
7996    if (ok == ECORE_CALLBACK_CANCEL)
7997      {
7998         sd->queue_filter_enterer = NULL;
7999         efl_event_callback_legacy_call(sd->obj, ELM_GENLIST_EVENT_FILTER_DONE, NULL);
8000      }
8001 
8002    return ok;
8003 }
8004 
8005 EOLIAN void
_elm_genlist_filter_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,void * filter_data)8006 _elm_genlist_filter_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, void *filter_data)
8007 {
8008    Item_Block *itb;
8009    Eina_List *l;
8010    Elm_Gen_Item *it;
8011 
8012    if (sd->filter_queue)
8013      ELM_SAFE_FREE(sd->queue_filter_enterer, ecore_idle_enterer_del);
8014    ELM_SAFE_FREE(sd->filter_queue, eina_list_free);
8015    ELM_SAFE_FREE(sd->filtered_list, eina_list_free);
8016    sd->filtered_count = 0;
8017    sd->processed_count = 0;
8018    sd->filter = EINA_TRUE;
8019    sd->filter_data = filter_data;
8020 
8021    EINA_INLIST_FOREACH(sd->blocks, itb)
8022      {
8023         if (itb->realized)
8024           {
8025              EINA_LIST_FOREACH(itb->items, l, it)
8026                {
8027                   it->filtered = EINA_FALSE;
8028                   it->hide = EINA_FALSE;
8029                   if (it->realized)
8030                     _filter_item_internal(it);
8031                   else
8032                     sd->filter_queue = eina_list_append(sd->filter_queue, it);
8033                }
8034             itb->changed = EINA_TRUE;
8035             evas_object_smart_changed(obj);
8036             sd->need_calc = EINA_TRUE;
8037          }
8038        else
8039          {
8040             EINA_LIST_FOREACH(itb->items, l, it)
8041               {
8042                  it->filtered = EINA_FALSE;
8043                  it->hide = EINA_FALSE;
8044                  sd->filter_queue = eina_list_append(sd->filter_queue, it);
8045               }
8046          }
8047      }
8048    if (!sd->filter_queue)
8049      efl_event_callback_legacy_call(sd->obj, ELM_GENLIST_EVENT_FILTER_DONE, NULL);
8050    else
8051      sd->queue_filter_enterer = ecore_idle_enterer_add(_item_filter_enterer,
8052                                                        sd->obj);
8053 }
8054 
8055 static Eina_Bool
_filter_iterator_next(Elm_Genlist_Filter * iter,void ** data)8056 _filter_iterator_next(Elm_Genlist_Filter *iter, void **data)
8057 {
8058    if (!iter->current) return EINA_FALSE;
8059    Elm_Gen_Item *item;
8060    while (iter->current)
8061      {
8062         item = ELM_GENLIST_FILTER_ITERATOR_ITEM_GET(iter->current, Elm_Gen_Item);
8063         iter->current = iter->current->next;
8064         if (_item_filtered_get(item, item->item->block->sd))
8065           {
8066              if (data)
8067                *data = EO_OBJ(item);
8068              return EINA_TRUE;
8069           }
8070      }
8071 
8072    return EINA_FALSE;
8073 }
8074 
8075 static void
_filter_iterator_free(Elm_Genlist_Filter * iter)8076 _filter_iterator_free(Elm_Genlist_Filter *iter)
8077 {
8078    free(iter);
8079 }
8080 
8081 static Evas_Object *
_filter_iterator_get_container(Elm_Genlist_Filter * iter)8082 _filter_iterator_get_container(Elm_Genlist_Filter *iter)
8083 {
8084    if (!iter) return NULL;
8085    return iter->obj;
8086 }
8087 
8088 EOLIAN Eina_Iterator *
_elm_genlist_filter_iterator_new(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8089 _elm_genlist_filter_iterator_new(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8090 {
8091    Elm_Genlist_Filter *iter;
8092    iter = calloc(1, sizeof (Elm_Genlist_Filter));
8093    if (!iter) return NULL;
8094 
8095    iter->head = sd->items;
8096    iter->current = sd->items;
8097    iter->obj = sd->obj;
8098 
8099    iter->iterator.version = EINA_ITERATOR_VERSION;
8100    iter->iterator.next = FUNC_ITERATOR_NEXT(_filter_iterator_next);
8101    iter->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
8102                                     _filter_iterator_get_container);
8103    iter->iterator.free = FUNC_ITERATOR_FREE(_filter_iterator_free);
8104 
8105    EINA_MAGIC_SET(&iter->iterator, EINA_MAGIC_ITERATOR);
8106 
8107    return &iter->iterator;
8108 }
8109 
8110 EOLIAN static unsigned int
_elm_genlist_filtered_items_count(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8111 _elm_genlist_filtered_items_count(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8112 {
8113    return sd->filtered_count;
8114 }
8115 
8116 EOLIAN static void
_elm_genlist_longpress_timeout_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,double timeout)8117 _elm_genlist_longpress_timeout_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, double timeout)
8118 {
8119    sd->longpress_timeout = timeout;
8120 }
8121 
8122 EOLIAN static double
_elm_genlist_longpress_timeout_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8123 _elm_genlist_longpress_timeout_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8124 {
8125    return sd->longpress_timeout;
8126 }
8127 
8128 EAPI void
elm_genlist_scroller_policy_set(Evas_Object * obj,Elm_Scroller_Policy policy_h,Elm_Scroller_Policy policy_v)8129 elm_genlist_scroller_policy_set(Evas_Object *obj,
8130                                 Elm_Scroller_Policy policy_h,
8131                                 Elm_Scroller_Policy policy_v)
8132 {
8133    ELM_GENLIST_CHECK(obj);
8134    elm_interface_scrollable_policy_set(obj, policy_h, policy_v);
8135 }
8136 
8137 EOLIAN static void
_elm_genlist_elm_interface_scrollable_policy_set(Eo * obj,Elm_Genlist_Data * sd EINA_UNUSED,Elm_Scroller_Policy policy_h,Elm_Scroller_Policy policy_v)8138 _elm_genlist_elm_interface_scrollable_policy_set(Eo *obj, Elm_Genlist_Data *sd EINA_UNUSED, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
8139 {
8140    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
8141        (policy_v >= ELM_SCROLLER_POLICY_LAST))
8142      return;
8143 
8144    elm_interface_scrollable_policy_set(efl_super(obj, MY_CLASS), policy_h, policy_v);
8145 }
8146 
8147 EAPI void
elm_genlist_scroller_policy_get(const Evas_Object * obj,Elm_Scroller_Policy * policy_h,Elm_Scroller_Policy * policy_v)8148 elm_genlist_scroller_policy_get(const Evas_Object *obj,
8149                                 Elm_Scroller_Policy *policy_h,
8150                                 Elm_Scroller_Policy *policy_v)
8151 {
8152    ELM_GENLIST_CHECK(obj);
8153    elm_interface_scrollable_policy_get(obj, policy_h, policy_v);
8154 }
8155 
8156 EOLIAN static void
_elm_genlist_elm_interface_scrollable_policy_get(const Eo * obj,Elm_Genlist_Data * sd EINA_UNUSED,Elm_Scroller_Policy * policy_h,Elm_Scroller_Policy * policy_v)8157 _elm_genlist_elm_interface_scrollable_policy_get(const Eo *obj, Elm_Genlist_Data *sd EINA_UNUSED, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
8158 {
8159    Elm_Scroller_Policy s_policy_h, s_policy_v;
8160 
8161    elm_interface_scrollable_policy_get
8162          (efl_super(obj, MY_CLASS), &s_policy_h, &s_policy_v);
8163    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
8164    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
8165 }
8166 
8167 EOLIAN static void
_elm_genlist_realized_items_update(Eo * obj,Elm_Genlist_Data * _pd)8168 _elm_genlist_realized_items_update(Eo *obj, Elm_Genlist_Data *_pd)
8169 {
8170    Eina_List *list;
8171    Elm_Object_Item *it;
8172 
8173    list = elm_genlist_realized_items_get(obj);
8174    EINA_LIST_FREE(list, it)
8175      {
8176         ELM_GENLIST_ITEM_DATA_GET(it, it2);
8177         if (!it2->item->block) continue;
8178         _mark_item_update(it2);
8179      }
8180    ecore_job_del(_pd->update_job);
8181    _pd->update_job = ecore_job_add(_update_job, obj);
8182 }
8183 
8184 EOLIAN static void
_elm_genlist_item_decorate_mode_set(Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it,const char * decorate_it_type,Eina_Bool decorate_it_set)8185 _elm_genlist_item_decorate_mode_set(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it,
8186                                    const char *decorate_it_type,
8187                                    Eina_Bool decorate_it_set)
8188 {
8189    Elm_Genlist_Data *sd;
8190    Eina_List *l;
8191    Elm_Object_Item *eo_it2 = NULL;
8192 
8193    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
8194    sd = it->item->wsd;
8195 
8196    if (!decorate_it_type) return;
8197    if (elm_wdg_item_disabled_get(eo_it)) return;
8198    if (sd->decorate_all_mode) return;
8199 
8200    if ((sd->mode_item == it) &&
8201        (!strcmp(decorate_it_type, sd->decorate_it_type)) &&
8202        (decorate_it_set))
8203      return;
8204    if (!it->itc->decorate_item_style) return;
8205    it->decorate_it_set = decorate_it_set;
8206 
8207    if (sd->multi)
8208      {
8209         EINA_LIST_FOREACH(sd->selected, l, eo_it2)
8210           {
8211              ELM_GENLIST_ITEM_DATA_GET(eo_it2, it2);
8212              if (it2->realized)
8213                 elm_genlist_item_selected_set(eo_it2, EINA_FALSE);
8214           }
8215      }
8216    else
8217      {
8218         Elm_Gen_Item *it2 = NULL;
8219         eo_it2 = elm_genlist_selected_item_get(sd->obj);
8220         if (eo_it2) it2 = efl_data_scope_get(eo_it2, ELM_GENLIST_ITEM_CLASS);
8221         if (it2 && it2->realized)
8222           elm_genlist_item_selected_set(eo_it2, EINA_FALSE);
8223      }
8224 
8225    if (!eina_streq(sd->decorate_it_type, decorate_it_type) ||
8226        decorate_it_set || (it == sd->mode_item))
8227      _decorate_item_unset(sd);
8228 
8229    eina_stringshare_replace(&sd->decorate_it_type, decorate_it_type);
8230    if (decorate_it_set) _decorate_item_set(it);
8231 }
8232 
8233 EOLIAN static const char *
_elm_genlist_item_decorate_mode_get(const Eo * eo_i EINA_UNUSED,Elm_Gen_Item * i)8234 _elm_genlist_item_decorate_mode_get(const Eo *eo_i EINA_UNUSED, Elm_Gen_Item *i)
8235 {
8236    ELM_GENLIST_ITEM_CHECK_OR_RETURN(i, NULL);
8237    return i->item->wsd->decorate_it_type;
8238 }
8239 
8240 EOLIAN static Elm_Object_Item *
_elm_genlist_decorated_item_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8241 _elm_genlist_decorated_item_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8242 {
8243    return EO_OBJ(sd->mode_item);
8244 }
8245 
8246 EOLIAN static Eina_Bool
_elm_genlist_decorate_mode_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8247 _elm_genlist_decorate_mode_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8248 {
8249    return sd->decorate_all_mode;
8250 }
8251 
8252 EOLIAN static void
_elm_genlist_decorate_mode_set(Eo * obj,Elm_Genlist_Data * sd,Eina_Bool decorated)8253 _elm_genlist_decorate_mode_set(Eo *obj, Elm_Genlist_Data *sd, Eina_Bool decorated)
8254 {
8255    Elm_Object_Item *eo_it;
8256    Eina_List *list;
8257 
8258    decorated = !!decorated;
8259    if (sd->decorate_all_mode == decorated) return;
8260    // decorate_all_mode should be set first
8261    // because content_get func. will be called after this
8262    // and user can check whether decorate_all_mode_ is enabled.
8263    sd->decorate_all_mode = decorated;
8264 
8265    _elm_genlist_tree_effect_stop(sd);
8266    sd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
8267 
8268    list = elm_genlist_realized_items_get(obj);
8269    if (!sd->decorate_all_mode)
8270      {
8271         EINA_LIST_FREE(list, eo_it)
8272           {
8273              ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
8274              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
8275                _decorate_all_item_unrealize(it);
8276           }
8277         _item_cache_zero(sd);
8278      }
8279    else
8280      {
8281         // unset decorated item
8282         Elm_Object_Item *deco_eo_it = elm_genlist_decorated_item_get(obj);
8283         ELM_GENLIST_ITEM_DATA_GET(deco_eo_it, deco_it);
8284         if (deco_it)
8285           {
8286              elm_genlist_item_decorate_mode_set
8287                (deco_eo_it, elm_genlist_item_decorate_mode_get
8288                  (deco_eo_it), EINA_FALSE);
8289              _decorate_item_finished_signal_cb(deco_it, obj, NULL, NULL);
8290           }
8291 
8292         EINA_LIST_FREE(list, eo_it)
8293           {
8294              ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
8295              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
8296                {
8297                   if (it->itc->decorate_all_item_style)
8298                     _decorate_all_item_realize(it, EINA_TRUE);
8299                }
8300           }
8301      }
8302 
8303    efl_canvas_group_change(sd->obj);
8304 }
8305 
8306 EOLIAN static void
_elm_genlist_reorder_mode_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool reorder_mode)8307 _elm_genlist_reorder_mode_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool reorder_mode)
8308 {
8309    Eina_List *realized;
8310    Elm_Object_Item *eo_it;
8311 
8312    if (sd->reorder_mode == !!reorder_mode) return;
8313    if (sd->pin_item) elm_genlist_item_pin_set(EO_OBJ(sd->pin_item), EINA_FALSE);
8314    sd->reorder_mode = !!reorder_mode;
8315    realized = elm_genlist_realized_items_get(obj);
8316    EINA_LIST_FREE(realized, eo_it)
8317     {
8318        ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
8319        if (sd->reorder_mode)
8320          {
8321             edje_object_signal_emit(VIEW(it), SIGNAL_REORDER_MODE_SET, "elm");
8322             if (it->deco_all_view)
8323               {
8324                  edje_object_signal_emit(it->deco_all_view,
8325                                          SIGNAL_REORDER_MODE_SET, "elm");
8326               }
8327          }
8328        else
8329          {
8330             edje_object_signal_emit(VIEW(it), SIGNAL_REORDER_MODE_UNSET, "elm");
8331             if (it->deco_all_view)
8332               {
8333                  edje_object_signal_emit(it->deco_all_view,
8334                                          SIGNAL_REORDER_MODE_UNSET, "elm");
8335               }
8336          }
8337     }
8338 }
8339 
8340 EOLIAN static Eina_Bool
_elm_genlist_reorder_mode_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8341 _elm_genlist_reorder_mode_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8342 {
8343    return sd->reorder_mode;
8344 }
8345 
8346 EOLIAN static Elm_Genlist_Item_Type
_elm_genlist_item_type_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)8347 _elm_genlist_item_type_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
8348 {
8349    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, ELM_GENLIST_ITEM_MAX);
8350 
8351    return it->item->type;
8352 }
8353 
8354 EOLIAN static void
_elm_genlist_item_pin_set(Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it,Eina_Bool pin)8355 _elm_genlist_item_pin_set(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it, Eina_Bool pin)
8356 {
8357    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
8358    ELM_GENLIST_DATA_GET(WIDGET(it), sd);
8359    if (sd->reorder_mode) return;
8360    if (it->item->type & ELM_GENLIST_ITEM_GROUP) return;
8361 
8362    if (pin ^ (sd->pin_item == it))
8363      {
8364         if (sd->pin_item)
8365           {
8366              if (sd->pin_item->item->block)
8367                 sd->pin_item->item->block->realized = EINA_TRUE;
8368              evas_object_smart_changed(sd->pan_obj);
8369           }
8370         if (pin)
8371           sd->pin_item = it;
8372         else
8373           sd->pin_item = NULL;
8374      }
8375 }
8376 
8377 EOLIAN static Eina_Bool
_elm_genlist_item_pin_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)8378 _elm_genlist_item_pin_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
8379 {
8380    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
8381    ELM_GENLIST_DATA_GET(WIDGET(it), sd);
8382 
8383    if (sd->pin_item == it)
8384      return EINA_TRUE;
8385    else
8386      return EINA_FALSE;
8387 }
8388 
8389 EAPI Elm_Genlist_Item_Class *
elm_genlist_item_class_new(void)8390 elm_genlist_item_class_new(void)
8391 {
8392    Elm_Genlist_Item_Class *itc = ELM_NEW(Elm_Genlist_Item_Class);
8393    EINA_SAFETY_ON_NULL_RETURN_VAL(itc, NULL);
8394 
8395    itc->version = CLASS_ALLOCATED;
8396    itc->refcount = 1;
8397    itc->delete_me = EINA_FALSE;
8398 
8399    return itc;
8400 }
8401 
8402 EAPI void
elm_genlist_item_class_free(Elm_Genlist_Item_Class * itc)8403 elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc)
8404 {
8405    if (itc && (itc->version == CLASS_ALLOCATED))
8406      {
8407         if (!itc->delete_me) itc->delete_me = EINA_TRUE;
8408         if (itc->refcount > 0) elm_genlist_item_class_unref(itc);
8409         else
8410           {
8411              itc->version = 0;
8412              free(itc);
8413           }
8414      }
8415 }
8416 
8417 EAPI void
elm_genlist_item_class_ref(Elm_Genlist_Item_Class * itc)8418 elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc)
8419 {
8420    if (itc && (itc->version == CLASS_ALLOCATED))
8421      {
8422         itc->refcount++;
8423         if (itc->refcount == 0) itc->refcount--;
8424      }
8425 }
8426 
8427 EAPI void
elm_genlist_item_class_unref(Elm_Genlist_Item_Class * itc)8428 elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc)
8429 {
8430    if (itc && (itc->version == CLASS_ALLOCATED))
8431      {
8432         if (itc->refcount > 0) itc->refcount--;
8433         if (itc->delete_me && (!itc->refcount))
8434           elm_genlist_item_class_free(itc);
8435      }
8436 }
8437 
8438 static void
_flip_job(void * data)8439 _flip_job(void *data)
8440 {
8441    Elm_Gen_Item *it = (Elm_Gen_Item *)data;
8442    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
8443 
8444    _item_unselect(it);
8445    _elm_genlist_item_unrealize(it, EINA_FALSE);
8446 
8447    it->flipped = EINA_TRUE;
8448    it->item->nocache = EINA_TRUE;
8449    efl_canvas_group_change(sd->obj);
8450 }
8451 
8452 EOLIAN static void
_elm_genlist_item_flip_set(Eo * eo_it,Elm_Gen_Item * it,Eina_Bool flip)8453 _elm_genlist_item_flip_set(Eo *eo_it, Elm_Gen_Item *it, Eina_Bool flip)
8454 {
8455    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
8456 
8457    flip = !!flip;
8458    if (it->flipped == flip) return;
8459 
8460    if (flip)
8461      {
8462         ecore_job_add(_flip_job, it);
8463      }
8464    else
8465      {
8466         edje_object_signal_emit(VIEW(it), SIGNAL_FLIP_DISABLED, "elm");
8467         if (it->item->wsd->decorate_all_mode)
8468           edje_object_signal_emit(it->deco_all_view, SIGNAL_FLIP_DISABLED,
8469                                   "elm");
8470 
8471         it->flipped = flip;
8472         _item_cache_zero(it->item->wsd);
8473         elm_genlist_item_update(eo_it);
8474         it->item->nocache = EINA_FALSE;
8475      }
8476 }
8477 
8478 EOLIAN static Eina_Bool
_elm_genlist_item_flip_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)8479 _elm_genlist_item_flip_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
8480 {
8481    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
8482 
8483    return it->flipped;
8484 }
8485 
8486 EOLIAN static void
_elm_genlist_select_mode_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Elm_Object_Select_Mode mode)8487 _elm_genlist_select_mode_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Elm_Object_Select_Mode mode)
8488 {
8489    if ((mode >= ELM_OBJECT_SELECT_MODE_MAX) || (sd->select_mode == mode))
8490      return;
8491 
8492    sd->select_mode = mode;
8493 
8494    if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
8495        (sd->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
8496      {
8497         Eina_List *l, *ll;
8498         Elm_Object_Item *eo_it;
8499         EINA_LIST_FOREACH_SAFE(sd->selected, l, ll, eo_it)
8500         {
8501            ELM_GENLIST_ITEM_DATA_GET(eo_it, it);
8502            _item_unselect(it);
8503         }
8504      }
8505 }
8506 
8507 EOLIAN static Elm_Object_Select_Mode
_elm_genlist_select_mode_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8508 _elm_genlist_select_mode_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8509 {
8510    return sd->select_mode;
8511 }
8512 
8513 EOLIAN static void
_elm_genlist_highlight_mode_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool highlight)8514 _elm_genlist_highlight_mode_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool highlight)
8515 {
8516    sd->highlight = !!highlight;
8517 }
8518 
8519 EOLIAN static Eina_Bool
_elm_genlist_highlight_mode_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8520 _elm_genlist_highlight_mode_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8521 {
8522    return sd->highlight;
8523 }
8524 
8525 EOLIAN static void
_elm_genlist_item_select_mode_set(Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it,Elm_Object_Select_Mode mode)8526 _elm_genlist_item_select_mode_set(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it,
8527                                  Elm_Object_Select_Mode mode)
8528 {
8529    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
8530    ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
8531 
8532    if ((mode >= ELM_OBJECT_SELECT_MODE_MAX) || (it->select_mode == mode))
8533      return;
8534 
8535    it->select_mode = mode;
8536 
8537    if ((it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
8538        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
8539      _item_unselect(it);
8540 
8541    if (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
8542      {
8543         it->item->mincalcd = EINA_FALSE;
8544         it->item->updateme = EINA_TRUE;
8545         if (it->item->block) it->item->block->updateme = EINA_TRUE;
8546         ecore_job_del(sd->update_job);
8547         sd->update_job = ecore_job_add(_update_job, sd->obj);
8548 
8549         // reset homogeneous item size
8550         if (sd->homogeneous)
8551           {
8552              Item_Size *size =
8553                 eina_hash_find(sd->size_caches, &(it->itc));
8554              if (size)
8555                eina_hash_del_by_key(sd->size_caches, it->itc);
8556           }
8557      }
8558 }
8559 
8560 EOLIAN static Elm_Object_Select_Mode
_elm_genlist_item_select_mode_get(const Eo * eo_it EINA_UNUSED,Elm_Gen_Item * it)8561 _elm_genlist_item_select_mode_get(const Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
8562 {
8563    ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, ELM_OBJECT_SELECT_MODE_MAX);
8564 
8565    return it->select_mode;
8566 }
8567 
8568 EOLIAN Efl_Access_State_Set
_elm_genlist_item_efl_access_object_state_set_get(const Eo * eo_it,Elm_Gen_Item * it EINA_UNUSED)8569 _elm_genlist_item_efl_access_object_state_set_get(const Eo *eo_it, Elm_Gen_Item *it EINA_UNUSED)
8570 {
8571    Efl_Access_State_Set ret;
8572    Eina_Bool sel;
8573 
8574    ret = efl_access_object_state_set_get(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS));
8575 
8576    sel = elm_obj_genlist_item_selected_get(eo_it);
8577 
8578    STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_SELECTABLE);
8579 
8580    if (sel)
8581       STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_SELECTED);
8582 
8583    if (elm_genlist_item_type_get(eo_it) == ELM_GENLIST_ITEM_TREE)
8584      {
8585         STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_EXPANDABLE);
8586         if (elm_genlist_item_expanded_get(eo_it))
8587            STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_EXPANDED);
8588      }
8589 
8590    return ret;
8591 }
8592 
8593 EOLIAN const char*
_elm_genlist_item_efl_access_object_i18n_name_get(const Eo * eo_it,Elm_Gen_Item * it)8594 _elm_genlist_item_efl_access_object_i18n_name_get(const Eo *eo_it, Elm_Gen_Item *it)
8595 {
8596    const char *ret;
8597    Eina_Strbuf *buf;
8598    char *accessible_name;
8599 
8600    ret = efl_access_object_i18n_name_get(efl_super(eo_it, ELM_GENLIST_ITEM_CLASS));
8601    if (ret) return ret;
8602 
8603    buf = eina_strbuf_new();
8604 
8605    if (it->itc->func.text_get)
8606      {
8607         Eina_List *texts;
8608         const char *key;
8609 
8610         texts =
8611            elm_widget_stringlist_get(edje_object_data_get(VIEW(it), "texts"));
8612 
8613         EINA_LIST_FREE(texts, key)
8614           {
8615              char *str_markup = it->itc->func.text_get
8616                 ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
8617              char *str_utf8 = _elm_util_mkup_to_text(str_markup);
8618 
8619              free(str_markup);
8620 
8621              if (str_utf8)
8622                {
8623                   if (eina_strbuf_length_get(buf) > 0) eina_strbuf_append(buf, ", ");
8624                   eina_strbuf_append(buf, str_utf8);
8625                   free(str_utf8);
8626                }
8627           }
8628      }
8629 
8630    accessible_name = eina_strbuf_string_steal(buf);
8631    eina_strbuf_free(buf);
8632 
8633    eina_stringshare_del(it->base->accessible_name);
8634    it->base->accessible_name = eina_stringshare_add(accessible_name);
8635    free(accessible_name);
8636    return it->base->accessible_name;
8637 }
8638 
8639 EOLIAN static void
_elm_genlist_tree_effect_enabled_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool enabled)8640 _elm_genlist_tree_effect_enabled_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool enabled)
8641 {
8642    sd->tree_effect_enabled = !!enabled;
8643 }
8644 
8645 EOLIAN static Eina_Bool
_elm_genlist_tree_effect_enabled_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8646 _elm_genlist_tree_effect_enabled_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8647 {
8648    return sd->tree_effect_enabled;
8649 }
8650 
8651 EOLIAN static void
_elm_genlist_focus_on_selection_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool enabled)8652 _elm_genlist_focus_on_selection_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool enabled)
8653 {
8654    sd->focus_on_selection_enabled = !!enabled;
8655 }
8656 
8657 EOLIAN static Eina_Bool
_elm_genlist_focus_on_selection_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8658 _elm_genlist_focus_on_selection_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8659 {
8660    return sd->focus_on_selection_enabled;
8661 }
8662 
8663 EAPI Elm_Object_Item *
elm_genlist_nth_item_get(const Evas_Object * obj,unsigned int nth)8664 elm_genlist_nth_item_get(const Evas_Object *obj, unsigned int nth)
8665 {
8666    Elm_Gen_Item *it = NULL;
8667    Eina_Accessor *a;
8668    void *data;
8669 
8670    ELM_GENLIST_CHECK(obj) NULL;
8671    ELM_GENLIST_DATA_GET(obj, sd);
8672 
8673    if (!sd->items) return NULL;
8674 
8675    a = eina_inlist_accessor_new(sd->items);
8676    if (!a) return NULL;
8677    if (eina_accessor_data_get(a, nth, &data))
8678      it = ELM_GEN_ITEM_FROM_INLIST(data);
8679    eina_accessor_free(a);
8680    return EO_OBJ(it);
8681 }
8682 
8683 EOLIAN static Eina_Rect
_elm_genlist_efl_ui_widget_focus_highlight_geometry_get(const Eo * obj,Elm_Genlist_Data * sd)8684 _elm_genlist_efl_ui_widget_focus_highlight_geometry_get(const Eo *obj, Elm_Genlist_Data *sd)
8685 {
8686    Evas_Coord ox, oy, oh, ow, item_x = 0, item_y = 0, item_w = 0, item_h = 0;
8687    Eina_Rect r = {};
8688 
8689    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
8690 
8691    if (sd->focused_item)
8692      {
8693         ELM_GENLIST_ITEM_DATA_GET(sd->focused_item, focus_it);
8694         evas_object_geometry_get(VIEW(focus_it), &item_x, &item_y, &item_w, &item_h);
8695         elm_widget_focus_highlight_focus_part_geometry_get(VIEW(focus_it), &item_x, &item_y, &item_w, &item_h);
8696      }
8697    else
8698      {
8699         evas_object_geometry_get(obj, &r.x, &r.y, &r.w, &r.h);
8700         return r;
8701      }
8702 
8703    r.x = item_x;
8704    r.y = item_y;
8705    r.w = item_w;
8706    r.h = item_h;
8707 
8708    if (item_y < oy)
8709      {
8710         r.y = oy;
8711      }
8712    if (item_y > (oy + oh - item_h))
8713      {
8714         r.y = oy + oh - item_h;
8715      }
8716 
8717    if ((item_x + item_w) > (ox + ow))
8718      {
8719         r.w = ow;
8720      }
8721    if (item_x < ox)
8722      {
8723         r.x = ox;
8724      }
8725 
8726    return r;
8727 }
8728 
8729 EOLIAN static Elm_Object_Item *
_elm_genlist_search_by_text_item_get(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Elm_Object_Item * item_to_search_from,const char * part_name,const char * pattern,Elm_Glob_Match_Flags flags)8730 _elm_genlist_search_by_text_item_get(Eo *obj EINA_UNUSED,
8731                                      Elm_Genlist_Data *sd,
8732                                      Elm_Object_Item *item_to_search_from,
8733                                      const char *part_name,
8734                                      const char *pattern,
8735                                      Elm_Glob_Match_Flags flags)
8736 {
8737    Elm_Gen_Item *it = NULL;
8738    char *str = NULL;
8739    Eina_Inlist *start = NULL;
8740    int fnflags = 0;
8741 
8742    if (!pattern) return NULL;
8743    if (!sd->items) return NULL;
8744 
8745    if (flags & ELM_GLOB_MATCH_NO_ESCAPE) fnflags |= FNM_NOESCAPE;
8746    if (flags & ELM_GLOB_MATCH_PATH) fnflags |= FNM_PATHNAME;
8747    if (flags & ELM_GLOB_MATCH_PERIOD) fnflags |= FNM_PERIOD;
8748 #ifdef FNM_CASEFOLD
8749    if (flags & ELM_GLOB_MATCH_NOCASE) fnflags |= FNM_CASEFOLD;
8750 #endif
8751 
8752    start = (item_to_search_from) ?
8753    EINA_INLIST_GET((Elm_Gen_Item *)efl_data_scope_get(item_to_search_from, ELM_GENLIST_ITEM_CLASS)) :
8754    sd->items;
8755    EINA_INLIST_FOREACH(start, it)
8756      {
8757         if (!it->itc->func.text_get) continue;
8758         str = it->itc->func.text_get((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), part_name);
8759         if (!str) continue;
8760         if (!fnmatch(pattern, str, fnflags))
8761           {
8762              free(str);
8763              return EO_OBJ(it);
8764           }
8765         free(str);
8766      }
8767    return NULL;
8768 }
8769 
8770 EOLIAN static Elm_Object_Item*
_elm_genlist_elm_widget_item_container_focused_item_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8771 _elm_genlist_elm_widget_item_container_focused_item_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8772 {
8773    return sd->focused_item;
8774 }
8775 
8776 EOLIAN static void
_elm_genlist_elm_interface_scrollable_item_loop_enabled_set(Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd,Eina_Bool enable)8777 _elm_genlist_elm_interface_scrollable_item_loop_enabled_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool enable)
8778 {
8779    sd->item_loop_enable = !!enable;
8780 }
8781 
8782 EOLIAN static Eina_Bool
_elm_genlist_elm_interface_scrollable_item_loop_enabled_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * sd)8783 _elm_genlist_elm_interface_scrollable_item_loop_enabled_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
8784 {
8785    return sd->item_loop_enable;
8786 }
8787 
8788 EOLIAN static void
_elm_genlist_class_constructor(Efl_Class * klass)8789 _elm_genlist_class_constructor(Efl_Class *klass)
8790 {
8791    if (_elm_config->access_mode)
8792       _elm_genlist_smart_focus_next_enable = EINA_TRUE;
8793 
8794    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
8795 }
8796 
8797 EOLIAN const Efl_Access_Action_Data *
_elm_genlist_efl_access_widget_action_elm_actions_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * pd EINA_UNUSED)8798 _elm_genlist_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *pd EINA_UNUSED)
8799 {
8800    static Efl_Access_Action_Data atspi_actions[] = {
8801           { "move,prior", "move", "prior", _key_action_move},
8802           { "move,next", "move", "next", _key_action_move},
8803           { "move,left", "move", "left", _key_action_move},
8804           { "move,right", "move", "right", _key_action_move},
8805           { "move,up", "move", "up", _key_action_move},
8806           { "move,up,multi", "move", "up_multi", _key_action_move},
8807           { "move,down", "move", "down", _key_action_move},
8808           { "move,down,multi", "move", "down_multi", _key_action_move},
8809           { "move,first", "move", "first", _key_action_move},
8810           { "move,last", "move", "last", _key_action_move},
8811           { "select", "select", NULL, _key_action_select},
8812           { "select,multi", "select", "multi", _key_action_select},
8813           { "escape", "escape", NULL, _key_action_escape},
8814           { NULL, NULL, NULL, NULL }
8815    };
8816    return &atspi_actions[0];
8817 }
8818 
8819 EOLIAN Eina_List*
_elm_genlist_efl_access_object_access_children_get(const Eo * obj,Elm_Genlist_Data * sd)8820 _elm_genlist_efl_access_object_access_children_get(const Eo *obj, Elm_Genlist_Data *sd)
8821 {
8822    Eina_List *ret = NULL, *ret2 = NULL;
8823    Elm_Gen_Item *it;
8824 
8825    EINA_INLIST_FOREACH(sd->items, it)
8826       ret = eina_list_append(ret, EO_OBJ(it));
8827 
8828    ret2 = efl_access_object_access_children_get(efl_super(obj, ELM_GENLIST_CLASS));
8829 
8830    return eina_list_merge(ret, ret2);
8831 }
8832 
8833 EOLIAN Efl_Access_State_Set
_elm_genlist_efl_access_object_state_set_get(const Eo * obj,Elm_Genlist_Data * sd EINA_UNUSED)8834 _elm_genlist_efl_access_object_state_set_get(const Eo *obj, Elm_Genlist_Data *sd EINA_UNUSED)
8835 {
8836    Efl_Access_State_Set ret;
8837 
8838    ret = efl_access_object_state_set_get(efl_super(obj, ELM_GENLIST_CLASS));
8839 
8840    STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_MANAGES_DESCENDANTS);
8841 
8842    if (elm_genlist_multi_select_get(obj))
8843      STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_MULTISELECTABLE);
8844 
8845    if (elm_genlist_reorder_mode_get(obj))
8846      STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_ANIMATED);
8847 
8848    return ret;
8849 }
8850 
8851 EOLIAN int
_elm_genlist_efl_access_selection_selected_children_count_get(const Eo * objm EINA_UNUSED,Elm_Genlist_Data * pd)8852 _elm_genlist_efl_access_selection_selected_children_count_get(const Eo *objm EINA_UNUSED, Elm_Genlist_Data *pd)
8853 {
8854    return eina_list_count(pd->selected);
8855 }
8856 
8857 EOLIAN Eo*
_elm_genlist_efl_access_selection_selected_child_get(const Eo * obj EINA_UNUSED,Elm_Genlist_Data * pd,int child_idx)8858 _elm_genlist_efl_access_selection_selected_child_get(const Eo *obj EINA_UNUSED, Elm_Genlist_Data *pd, int child_idx)
8859 {
8860    return eina_list_nth(pd->selected, child_idx);
8861 }
8862 
8863 EOLIAN Eina_Bool
_elm_genlist_efl_access_selection_child_select(Eo * obj EINA_UNUSED,Elm_Genlist_Data * pd,int child_index)8864 _elm_genlist_efl_access_selection_child_select(Eo *obj EINA_UNUSED, Elm_Genlist_Data *pd, int child_index)
8865 {
8866    Elm_Gen_Item *item;
8867    if (pd->select_mode != ELM_OBJECT_SELECT_MODE_NONE)
8868      {
8869         EINA_INLIST_FOREACH(pd->items, item)
8870           {
8871              if (child_index-- == 0)
8872                {
8873                   elm_genlist_item_selected_set(EO_OBJ(item), EINA_TRUE);
8874                   return EINA_TRUE;
8875                }
8876           }
8877      }
8878    return EINA_FALSE;
8879 }
8880 
8881 EOLIAN Eina_Bool
_elm_genlist_efl_access_selection_selected_child_deselect(Eo * obj EINA_UNUSED,Elm_Genlist_Data * pd,int child_index)8882 _elm_genlist_efl_access_selection_selected_child_deselect(Eo *obj EINA_UNUSED, Elm_Genlist_Data *pd, int child_index)
8883 {
8884    Eo *item;
8885    Eina_List *l;
8886 
8887    EINA_LIST_FOREACH(pd->selected, l, item)
8888      {
8889         if (child_index-- == 0)
8890           {
8891              elm_genlist_item_selected_set(item, EINA_FALSE);
8892              return EINA_TRUE;
8893           }
8894      }
8895    return EINA_FALSE;
8896 }
8897 
8898 EOLIAN Eina_Bool
_elm_genlist_efl_access_selection_is_child_selected(Eo * obj EINA_UNUSED,Elm_Genlist_Data * pd,int child_index)8899 _elm_genlist_efl_access_selection_is_child_selected(Eo *obj EINA_UNUSED, Elm_Genlist_Data *pd, int child_index)
8900 {
8901    Elm_Gen_Item *item;
8902 
8903    EINA_INLIST_FOREACH(pd->items, item)
8904      {
8905         if (child_index-- == 0)
8906           {
8907              return elm_genlist_item_selected_get(EO_OBJ(item));
8908           }
8909      }
8910    return EINA_FALSE;
8911 }
8912 
8913 EOLIAN Eina_Bool
_elm_genlist_efl_access_selection_all_children_select(Eo * obj,Elm_Genlist_Data * pd)8914 _elm_genlist_efl_access_selection_all_children_select(Eo *obj, Elm_Genlist_Data *pd)
8915 {
8916    Elm_Gen_Item *item;
8917 
8918    if (!elm_genlist_multi_select_get(obj))
8919      return EINA_FALSE;
8920 
8921    EINA_INLIST_FOREACH(pd->items, item)
8922       elm_genlist_item_selected_set(EO_OBJ(item), EINA_TRUE);
8923 
8924    return EINA_TRUE;
8925 }
8926 
8927 EOLIAN Eina_Bool
_elm_genlist_efl_access_selection_access_selection_clear(Eo * obj EINA_UNUSED,Elm_Genlist_Data * pd)8928 _elm_genlist_efl_access_selection_access_selection_clear(Eo *obj EINA_UNUSED, Elm_Genlist_Data *pd)
8929 {
8930    return _all_items_deselect(pd);
8931 }
8932 
8933 EOLIAN Eina_Bool
_elm_genlist_efl_access_selection_child_deselect(Eo * obj EINA_UNUSED,Elm_Genlist_Data * pd,int child_index)8934 _elm_genlist_efl_access_selection_child_deselect(Eo *obj EINA_UNUSED, Elm_Genlist_Data *pd, int child_index)
8935 {
8936    Elm_Gen_Item *item;
8937    if (pd->select_mode != ELM_OBJECT_SELECT_MODE_NONE)
8938      {
8939         EINA_INLIST_FOREACH(pd->items, item)
8940           {
8941              if (child_index-- == 0)
8942                {
8943                   elm_genlist_item_selected_set(EO_OBJ(item), EINA_FALSE);
8944                   return EINA_TRUE;
8945                }
8946           }
8947      }
8948    return EINA_FALSE;
8949 }
8950 
8951 EOLIAN static Efl_Object*
_elm_genlist_efl_object_provider_find(const Eo * obj,Elm_Genlist_Data * pd,const Efl_Object * klass)8952 _elm_genlist_efl_object_provider_find(const Eo *obj, Elm_Genlist_Data *pd, const Efl_Object *klass)
8953 {
8954    if (klass == EFL_UI_FOCUS_PARENT_PROVIDER_INTERFACE)
8955      return pd->provider;
8956    return efl_provider_find(efl_super(obj, ELM_GENLIST_CLASS), klass);
8957 }
8958 
8959 EOLIAN static void
_elm_genlist_item_efl_ui_focus_object_setup_order_non_recursive(Eo * obj,Elm_Gen_Item * pd)8960 _elm_genlist_item_efl_ui_focus_object_setup_order_non_recursive(Eo *obj, Elm_Gen_Item *pd)
8961 {
8962    Eina_List *n;
8963    Efl_Ui_Widget *wid;
8964 
8965    EINA_LIST_FOREACH(pd->contents, n, wid)
8966      {
8967         if (efl_isa(wid, EFL_UI_WIDGET_CLASS))
8968           _elm_widget_full_eval(wid);
8969      }
8970 
8971    if (pd->realized)
8972      efl_ui_focus_object_setup_order_non_recursive(efl_super(obj, ELM_GENLIST_ITEM_CLASS));
8973 }
8974 
8975 EOLIAN static Eina_Bool
_elm_genlist_efl_ui_widget_focus_state_apply(Eo * obj,Elm_Genlist_Data * pd EINA_UNUSED,Efl_Ui_Widget_Focus_State current_state,Efl_Ui_Widget_Focus_State * configured_state,Efl_Ui_Widget * redirect EINA_UNUSED)8976 _elm_genlist_efl_ui_widget_focus_state_apply(Eo *obj, Elm_Genlist_Data *pd EINA_UNUSED, Efl_Ui_Widget_Focus_State current_state, Efl_Ui_Widget_Focus_State *configured_state, Efl_Ui_Widget *redirect EINA_UNUSED)
8977 {
8978    return efl_ui_widget_focus_state_apply(efl_super(obj, MY_CLASS), current_state, configured_state, obj);
8979 }
8980 
8981 EOLIAN static Efl_Ui_Focus_Object*
_elm_genlist_item_efl_ui_focus_object_focus_parent_get(const Eo * obj EINA_UNUSED,Elm_Gen_Item * pd)8982 _elm_genlist_item_efl_ui_focus_object_focus_parent_get(const Eo *obj EINA_UNUSED, Elm_Gen_Item *pd)
8983 {
8984    if (!pd->item->block) return NULL;
8985    return pd->item->block->adapter;
8986 }
8987 
8988 /* Standard widget overrides */
8989 
8990 ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(elm_genlist, Elm_Genlist_Data)
8991 
8992 /* Internal EO APIs and hidden overrides */
8993 
8994 #define ELM_GENLIST_EXTRA_OPS \
8995    EFL_CANVAS_GROUP_CALC_OPS(elm_genlist), \
8996    EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_genlist)
8997 
8998 #define ELM_GENLIST_PAN_EXTRA_OPS \
8999    EFL_CANVAS_GROUP_DEL_OPS(elm_genlist_pan)
9000 
9001 #include "elm_genlist_eo.c"
9002 #include "elm_genlist_pan_eo.c"
9003 #include "elm_genlist_item_eo.c"
9004