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