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