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