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