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