From: Hyoyoung Chang <hyoyoung@gmail.com>
[framework/uifw/elementary.git] / src / lib / elm_genlist.c
1 #include <assert.h>
2 #include <fnmatch.h>
3 #include <Elementary.h>
4 #include <Elementary_Cursor.h>
5 #include "elm_priv.h"
6 #include "els_scroller.h"
7 #include "elm_gen_common.h"
8
9 // internally allocated
10 #define CLASS_ALLOCATED 0x3a70f11f
11
12 #define MAX_ITEMS_PER_BLOCK 32
13 #define REORDER_EFFECT_TIME 0.5
14
15 #define ELM_GEN_SETUP(wd) \
16    (wd)->calc_cb = (Ecore_Cb)_calc_job; \
17    (wd)->clear_cb = (Ecore_Cb)_clear_cb; \
18    (wd)->sizing_cb = (Ecore_Cb)_sizing_eval
19
20 #define ELM_GEN_ITEM_SETUP(it) \
21    (it)->del_cb = (Ecore_Cb)_item_del; \
22    (it)->highlight_cb = (Ecore_Cb)_item_highlight; \
23    (it)->unsel_cb = (Ecore_Cb)_item_unselect; \
24    (it)->unhighlight_cb = (Ecore_Cb)_item_unhighlight; \
25    (it)->unrealize_cb = (Ecore_Cb)_item_unrealize_cb
26
27 #define ELM_GENLIST_CHECK_ITC_VER(itc) \
28    do \
29      { \
30         if (!itc) \
31           { \
32              ERR("Genlist_Item_Class(itc) is NULL"); \
33              return; \
34           } \
35         if ((itc->version != ELM_GENLIST_ITEM_CLASS_VERSION) && \
36             (itc->version != CLASS_ALLOCATED)) \
37           { \
38              ERR("Genlist_Item_Class version mismatched! current = (%d), required = (%d) or (%d)", itc->version, ELM_GENLIST_ITEM_CLASS_VERSION, CLASS_ALLOCATED); \
39              return; \
40           } \
41      } \
42    while(0)
43
44 typedef struct _Item_Block  Item_Block;
45 typedef struct _Item_Cache  Item_Cache;
46
47 struct Elm_Gen_Item_Type
48 {
49    Elm_Gen_Item                 *it;
50    Item_Block                   *block;
51    Eina_List                    *items;
52    Evas_Coord                    w, h, minw, minh;
53    Elm_Gen_Item                 *group_item;
54    Elm_Genlist_Item_Type        type;
55    Eina_List                    *mode_texts, *mode_contents, *mode_states, *mode_content_objs;
56    Eina_List                    *edit_texts, *edit_contents, *edit_states, *edit_content_objs;
57    Ecore_Timer                  *swipe_timer;
58    Evas_Coord                    scrl_x, scrl_y, old_scrl_y;
59
60    Elm_Gen_Item                 *rel;
61    Evas_Object                  *mode_view;
62    int                           expanded_depth;
63    int                           order_num_in;
64
65    Eina_Bool                     before : 1;
66
67    Eina_Bool                     want_realize : 1;
68    Eina_Bool                     expanded : 1;
69    Eina_Bool                     mincalcd : 1;
70    Eina_Bool                     queued : 1;
71    Eina_Bool                     showme : 1;
72    Eina_Bool                     updateme : 1;
73    Eina_Bool                     nocache : 1; /* do not use cache for this item */
74    Eina_Bool                     nocache_once : 1; /* do not use cache for this item only once */
75    Eina_Bool                     stacking_even : 1;
76    Eina_Bool                     nostacking : 1;
77    Eina_Bool                     move_effect_enabled : 1;
78    Eina_Bool                     decorate_mode_item_realized : 1;
79    Eina_Bool                     tree_effect_finished : 1; /* tree effect */
80 };
81
82 struct _Item_Block
83 {
84    EINA_INLIST;
85    int          count;
86    int          num;
87    int          reorder_offset;
88    Widget_Data *wd;
89    Eina_List   *items;
90    Evas_Coord   x, y, w, h, minw, minh;
91    int          position;
92    int          item_position_stamp;
93
94    Eina_Bool    position_update : 1;
95    Eina_Bool    want_unrealize : 1;
96    Eina_Bool    realized : 1;
97    Eina_Bool    changed : 1;
98    Eina_Bool    updateme : 1;
99    Eina_Bool    showme : 1;
100    Eina_Bool    must_recalc : 1;
101 };
102
103 struct _Item_Cache
104 {
105    EINA_INLIST;
106
107    Evas_Object *base_view, *spacer;
108
109    const char  *item_style; // it->itc->item_style
110    Eina_Bool    tree : 1; // it->group
111
112    Eina_Bool    selected : 1; // it->selected
113    Eina_Bool    disabled : 1; // it->disabled
114    Eina_Bool    expanded : 1; // it->item->expanded
115 };
116
117 static const char *widtype = NULL;
118 static void      _item_cache_zero(Widget_Data *wd);
119 static void      _del_hook(Evas_Object *obj);
120 static void      _mirrored_set(Evas_Object *obj,
121                                Eina_Bool    rtl);
122 static void      _theme_hook(Evas_Object *obj);
123 static void      _show_region_hook(void        *data,
124                                    Evas_Object *obj);
125 static void      _sizing_eval(Evas_Object *obj);
126 static void      _item_realize(Elm_Gen_Item *it,
127                                int           in,
128                                Eina_Bool     calc);
129 static void      _item_unrealize_cb(Elm_Gen_Item *it);
130 static void      _item_block_unrealize(Item_Block *itb);
131 static void      _calc_job(void *data);
132 static void      _on_focus_hook(void        *data,
133                                 Evas_Object *obj);
134 static Eina_Bool _item_multi_select_up(Widget_Data *wd);
135 static Eina_Bool _item_multi_select_down(Widget_Data *wd);
136 static Eina_Bool _item_single_select_up(Widget_Data *wd);
137 static Eina_Bool _item_single_select_down(Widget_Data *wd);
138 static Eina_Bool _event_hook(Evas_Object       *obj,
139                              Evas_Object       *src,
140                              Evas_Callback_Type type,
141                              void              *event_info);
142 static void      _signal_emit_hook(Evas_Object *obj,
143                                    const char  *emission,
144                                    const char  *source);
145 static Eina_Bool _deselect_all_items(Widget_Data *wd);
146 static void      _pan_calculate(Evas_Object *obj);
147 static void      _pan_max_get(Evas_Object *obj,
148                               Evas_Coord  *x,
149                               Evas_Coord  *y);
150 static void      _item_position(Elm_Gen_Item *it,
151                                 Evas_Object  *obj,
152                                 Evas_Coord    it_x,
153                                 Evas_Coord    it_y);
154 static void      _mode_item_realize(Elm_Gen_Item *it);
155 static void      _mode_item_unrealize(Elm_Gen_Item *it);
156 static void      _item_mode_set(Elm_Gen_Item *it);
157 static void      _item_mode_unset(Widget_Data *wd);
158 static void      _decorate_mode_item_position(Elm_Gen_Item *it, int itx, int ity);
159 static void      _decorate_mode_item_realize(Elm_Gen_Item *it, Eina_Bool effect_on);
160 static void      _decorate_mode_item_unrealize(Elm_Gen_Item *it);
161 static void      _group_items_recalc(void *data);
162 static void      _item_move_after(Elm_Gen_Item *it,
163                                   Elm_Gen_Item *after);
164 static void      _item_move_before(Elm_Gen_Item *it,
165                                    Elm_Gen_Item *before);
166 static void      _item_auto_scroll(Widget_Data *wd);
167 static void      _elm_genlist_clear(Evas_Object *obj,
168                                     Eina_Bool    standby);
169 static void      _pan_child_size_get(Evas_Object *obj,
170                                      Evas_Coord  *w,
171                                      Evas_Coord  *h);
172 static Evas_Object* _create_tray_alpha_bg(const Evas_Object *obj);
173 static void         _item_contract_emit(Elm_Gen_Item *it);
174 static int          _item_tree_effect_before(Elm_Gen_Item *it);
175 static void         _item_tree_effect(Widget_Data *wd, int y);
176 static void         _item_tree_effect_finish(Widget_Data *wd);
177 static Eina_Bool    _tree_effect_animator_cb(void *data);
178
179 static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
180
181 static const char SIG_ACTIVATED[] = "activated";
182 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
183 static const char SIG_SELECTED[] = "selected";
184 static const char SIG_UNSELECTED[] = "unselected";
185 static const char SIG_EXPANDED[] = "expanded";
186 static const char SIG_CONTRACTED[] = "contracted";
187 static const char SIG_EXPAND_REQUEST[] = "expand,request";
188 static const char SIG_CONTRACT_REQUEST[] = "contract,request";
189 static const char SIG_REALIZED[] = "realized";
190 static const char SIG_UNREALIZED[] = "unrealized";
191 static const char SIG_DRAG_START_UP[] = "drag,start,up";
192 static const char SIG_DRAG_START_DOWN[] = "drag,start,down";
193 static const char SIG_DRAG_START_LEFT[] = "drag,start,left";
194 static const char SIG_DRAG_START_RIGHT[] = "drag,start,right";
195 static const char SIG_DRAG_STOP[] = "drag,stop";
196 static const char SIG_DRAG[] = "drag";
197 static const char SIG_LONGPRESSED[] = "longpressed";
198 static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
199 static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
200 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
201 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
202 static const char SIG_EDGE_TOP[] = "edge,top";
203 static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
204 static const char SIG_EDGE_LEFT[] = "edge,left";
205 static const char SIG_EDGE_RIGHT[] = "edge,right";
206 static const char SIG_MULTI_SWIPE_LEFT[] = "multi,swipe,left";
207 static const char SIG_MULTI_SWIPE_RIGHT[] = "multi,swipe,right";
208 static const char SIG_MULTI_SWIPE_UP[] = "multi,swipe,up";
209 static const char SIG_MULTI_SWIPE_DOWN[] = "multi,swipe,down";
210 static const char SIG_MULTI_PINCH_OUT[] = "multi,pinch,out";
211 static const char SIG_MULTI_PINCH_IN[] = "multi,pinch,in";
212 static const char SIG_SWIPE[] = "swipe";
213 static const char SIG_MOVED[] = "moved";
214 static const char SIG_INDEX_UPDATE[] = "index,update";
215 static const char SIG_TREE_EFFECT_FINISHED [] = "tree,effect,finished";
216
217 static const Evas_Smart_Cb_Description _signals[] = {
218    {SIG_CLICKED_DOUBLE, ""},
219    {SIG_ACTIVATED, ""},
220    {SIG_SELECTED, ""},
221    {SIG_UNSELECTED, ""},
222    {SIG_EXPANDED, ""},
223    {SIG_CONTRACTED, ""},
224    {SIG_EXPAND_REQUEST, ""},
225    {SIG_CONTRACT_REQUEST, ""},
226    {SIG_REALIZED, ""},
227    {SIG_UNREALIZED, ""},
228    {SIG_DRAG_START_UP, ""},
229    {SIG_DRAG_START_DOWN, ""},
230    {SIG_DRAG_START_LEFT, ""},
231    {SIG_DRAG_START_RIGHT, ""},
232    {SIG_DRAG_STOP, ""},
233    {SIG_DRAG, ""},
234    {SIG_LONGPRESSED, ""},
235    {SIG_SCROLL_ANIM_START, ""},
236    {SIG_SCROLL_ANIM_STOP, ""},
237    {SIG_SCROLL_DRAG_START, ""},
238    {SIG_SCROLL_DRAG_STOP, ""},
239    {SIG_EDGE_TOP, ""},
240    {SIG_EDGE_BOTTOM, ""},
241    {SIG_EDGE_LEFT, ""},
242    {SIG_EDGE_RIGHT, ""},
243    {SIG_MULTI_SWIPE_LEFT, ""},
244    {SIG_MULTI_SWIPE_RIGHT, ""},
245    {SIG_MULTI_SWIPE_UP, ""},
246    {SIG_MULTI_SWIPE_DOWN, ""},
247    {SIG_MULTI_PINCH_OUT, ""},
248    {SIG_MULTI_PINCH_IN, ""},
249    {SIG_SWIPE, ""},
250    {SIG_MOVED, ""},
251    {SIG_TREE_EFFECT_FINISHED, ""},
252    {NULL, NULL}
253 };
254
255 /* TEMPORARY */
256 #undef ELM_CHECK_WIDTYPE
257 #define ELM_CHECK_WIDTYPE(obj, widtype) \
258    if ((!obj) || (!elm_genlist_type_check((obj), __func__))) return
259 #undef ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN
260 #define ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, ...)                \
261    ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
262    ELM_CHECK_WIDTYPE(WIDGET((it)), widtype) __VA_ARGS__;
263
264 static const char *_gengrid = NULL;
265 static const char *_genlist = NULL;
266
267 /* THIS FUNCTION IS HACKY AND TEMPORARY!!! */
268 Eina_Bool
269 elm_genlist_type_check(const Evas_Object *obj,
270                        const char        *func)
271 {
272    const char *provided, *expected = "(unknown)";
273    static int abort_on_warn = -1;
274    provided = elm_widget_type_get(obj);
275    if (!_genlist) _genlist = eina_stringshare_add("genlist");
276    if (!_gengrid) _gengrid = eina_stringshare_add("gengrid");
277    if (EINA_LIKELY(provided == _genlist) || EINA_LIKELY(provided == _gengrid))
278      return EINA_TRUE;
279    if ((!provided) || (!provided[0]))
280      {
281         provided = evas_object_type_get(obj);
282         if ((!provided) || (!provided[0]))
283           provided = "(unknown)";
284      }
285    ERR("Passing Object: %p in function: %s, of type: '%s' when expecting type: '%s'", obj, func, provided, expected);
286    if (abort_on_warn == -1)
287      {
288         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
289         else abort_on_warn = 0;
290      }
291    if (abort_on_warn == 1) abort();
292    return EINA_FALSE;
293 }
294
295 static Eina_Bool
296 _event_hook(Evas_Object       *obj,
297             Evas_Object       *src __UNUSED__,
298             Evas_Callback_Type type,
299             void              *event_info)
300 {
301    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
302    Evas_Event_Key_Down *ev = event_info;
303    Widget_Data *wd = elm_widget_data_get(obj);
304    Evas_Coord pan_max_x = 0, pan_max_y = 0;
305    if (!wd) return EINA_FALSE;
306    if (!wd->items) return EINA_FALSE;
307    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
308    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
309
310    Elm_Object_Item *it = NULL;
311    Evas_Coord x = 0;
312    Evas_Coord y = 0;
313    Evas_Coord step_x = 0;
314    Evas_Coord step_y = 0;
315    Evas_Coord v_w = 0;
316    Evas_Coord v_h = 0;
317    Evas_Coord page_x = 0;
318    Evas_Coord page_y = 0;
319
320    elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
321    elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
322    elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
323    elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
324
325    if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
326      {
327         x -= step_x;
328      }
329    else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
330      {
331         x += step_x;
332      }
333    else if ((!strcmp(ev->keyname, "Up")) || (!strcmp(ev->keyname, "KP_Up")))
334      {
335         if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
336              (_item_multi_select_up(wd)))
337             || (_item_single_select_up(wd)))
338           {
339              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
340              return EINA_TRUE;
341           }
342         else
343           y -= step_y;
344      }
345    else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
346      {
347         if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
348              (_item_multi_select_down(wd)))
349             || (_item_single_select_down(wd)))
350           {
351              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
352              return EINA_TRUE;
353           }
354         else
355           y += step_y;
356      }
357    else if ((!strcmp(ev->keyname, "Home")) || (!strcmp(ev->keyname, "KP_Home")))
358      {
359         it = elm_genlist_first_item_get(obj);
360         elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_IN);
361         elm_genlist_item_selected_set(it, EINA_TRUE);
362         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
363         return EINA_TRUE;
364      }
365    else if ((!strcmp(ev->keyname, "End")) || (!strcmp(ev->keyname, "KP_End")))
366      {
367         it = elm_genlist_last_item_get(obj);
368         elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_IN);
369         elm_genlist_item_selected_set(it, EINA_TRUE);
370         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
371         return EINA_TRUE;
372      }
373    else if ((!strcmp(ev->keyname, "Prior")) || (!strcmp(ev->keyname, "KP_Prior")))
374      {
375         if (page_y < 0)
376           y -= -(page_y * v_h) / 100;
377         else
378           y -= page_y;
379      }
380    else if ((!strcmp(ev->keyname, "Next")) || (!strcmp(ev->keyname, "KP_Next")))
381      {
382         if (page_y < 0)
383           y += -(page_y * v_h) / 100;
384         else
385           y += page_y;
386      }
387    else if (!strcmp(ev->keyname, "Escape"))
388      {
389         if (!_deselect_all_items(wd)) return EINA_FALSE;
390         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
391         return EINA_TRUE;
392      }
393    else if (((!strcmp(ev->keyname, "Return")) ||
394              (!strcmp(ev->keyname, "KP_Enter")) ||
395              (!strcmp(ev->keyname, "space")))
396             && (!wd->multi) && (wd->selected))
397      {
398         it = elm_genlist_selected_item_get(obj);
399         elm_genlist_item_expanded_set(it,
400                                       !elm_genlist_item_expanded_get(it));
401         evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
402      }
403    else return EINA_FALSE;
404
405    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
406    _pan_max_get(wd->pan_smart, &pan_max_x, &pan_max_y);
407    if (x < 0) x = 0;
408    if (x > pan_max_x) x = pan_max_x;
409    if (y < 0) y = 0;
410    if (y > pan_max_y) y = pan_max_y;
411    elm_smart_scroller_child_pos_set(wd->scr, x, y);
412    return EINA_TRUE;
413 }
414
415 static Eina_Bool
416 _deselect_all_items(Widget_Data *wd)
417 {
418    if (!wd->selected) return EINA_FALSE;
419    while (wd->selected)
420      elm_genlist_item_selected_set(wd->selected->data, EINA_FALSE);
421
422    return EINA_TRUE;
423 }
424
425 static Eina_Bool
426 _item_multi_select_up(Widget_Data *wd)
427 {
428    if (!wd->selected) return EINA_FALSE;
429    if (!wd->multi) return EINA_FALSE;
430
431    Elm_Object_Item *prev = elm_genlist_item_prev_get(wd->last_selected_item);
432    if (!prev) return EINA_TRUE;
433
434    if (elm_genlist_item_selected_get(prev))
435      {
436         elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
437         wd->last_selected_item = prev;
438         elm_genlist_item_show(wd->last_selected_item, ELM_GENLIST_ITEM_SCROLLTO_IN);
439      }
440    else
441      {
442         elm_genlist_item_selected_set(prev, EINA_TRUE);
443         elm_genlist_item_show(prev, ELM_GENLIST_ITEM_SCROLLTO_IN);
444      }
445    return EINA_TRUE;
446 }
447
448 static Eina_Bool
449 _item_multi_select_down(Widget_Data *wd)
450 {
451    if (!wd->selected) return EINA_FALSE;
452    if (!wd->multi) return EINA_FALSE;
453
454    Elm_Object_Item *next;
455    next = elm_genlist_item_next_get(wd->last_selected_item);
456    if (!next) return EINA_TRUE;
457
458    if (elm_genlist_item_selected_get(next))
459      {
460         elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
461         wd->last_selected_item = next;
462         elm_genlist_item_show(wd->last_selected_item, ELM_GENLIST_ITEM_SCROLLTO_IN);
463      }
464    else
465      {
466         elm_genlist_item_selected_set(next, EINA_TRUE);
467         elm_genlist_item_show(next, ELM_GENLIST_ITEM_SCROLLTO_IN);
468      }
469    return EINA_TRUE;
470 }
471
472 static Eina_Bool
473 _item_single_select_up(Widget_Data *wd)
474 {
475    Elm_Gen_Item *prev;
476    if (!wd->selected)
477      {
478         prev = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
479         while ((prev) && (prev->generation < wd->generation))
480           prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
481      }
482    else prev = (Elm_Gen_Item *) elm_genlist_item_prev_get(wd->last_selected_item);
483
484    if (!prev) return EINA_FALSE;
485
486    _deselect_all_items(wd);
487
488    elm_genlist_item_selected_set((Elm_Object_Item *) prev, EINA_TRUE);
489    elm_genlist_item_show((Elm_Object_Item *) prev, ELM_GENLIST_ITEM_SCROLLTO_IN);
490    return EINA_TRUE;
491 }
492
493 static Eina_Bool
494 _item_single_select_down(Widget_Data *wd)
495 {
496    Elm_Gen_Item *next;
497    if (!wd->selected)
498      {
499         next = ELM_GEN_ITEM_FROM_INLIST(wd->items);
500         while ((next) && (next->generation < wd->generation))
501           next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
502      }
503    else next = (Elm_Gen_Item *) elm_genlist_item_next_get(wd->last_selected_item);
504
505    if (!next) return EINA_FALSE;
506
507    _deselect_all_items(wd);
508
509    elm_genlist_item_selected_set((Elm_Object_Item *) next, EINA_TRUE);
510    elm_genlist_item_show((Elm_Object_Item *) next, ELM_GENLIST_ITEM_SCROLLTO_IN);
511    return EINA_TRUE;
512 }
513
514 static void
515 _on_focus_hook(void        *data __UNUSED__,
516                Evas_Object *obj)
517 {
518    Widget_Data *wd = elm_widget_data_get(obj);
519    if (!wd) return;
520    if (elm_widget_focus_get(obj))
521      {
522         elm_object_signal_emit(wd->obj, "elm,action,focus", "elm");
523         evas_object_focus_set(wd->obj, EINA_TRUE);
524         if ((wd->selected) && (!wd->last_selected_item))
525           wd->last_selected_item = eina_list_data_get(wd->selected);
526      }
527    else
528      {
529         elm_object_signal_emit(wd->obj, "elm,action,unfocus", "elm");
530         evas_object_focus_set(wd->obj, EINA_FALSE);
531      }
532 }
533
534 static void
535 _del_hook(Evas_Object *obj)
536 {
537    Widget_Data *wd = elm_widget_data_get(obj);
538    if (!wd) return;
539    _item_cache_zero(wd);
540    if (wd->calc_job) ecore_job_del(wd->calc_job);
541    if (wd->update_job) ecore_job_del(wd->update_job);
542    if (wd->queue_idle_enterer) ecore_idle_enterer_del(wd->queue_idle_enterer);
543    if (wd->must_recalc_idler) ecore_idler_del(wd->must_recalc_idler);
544    if (wd->multi_timer) ecore_timer_del(wd->multi_timer);
545    if (wd->decorate_type) eina_stringshare_del(wd->decorate_type);
546    if (wd->scr_hold_timer) ecore_timer_del(wd->scr_hold_timer);
547    free(wd);
548 }
549
550 static void
551 _del_pre_hook(Evas_Object *obj)
552 {
553    Widget_Data *wd = elm_widget_data_get(obj);
554    if (!wd) return;
555    if (wd->decorate_mode) elm_genlist_decorate_mode_set(wd->obj, EINA_FALSE);
556    elm_genlist_clear(obj);
557    evas_object_del(wd->pan_smart);
558    wd->pan_smart = NULL;
559 }
560
561 static void
562 _mirrored_set(Evas_Object *obj,
563               Eina_Bool    rtl)
564 {
565    Widget_Data *wd = elm_widget_data_get(obj);
566    if (!wd) return;
567    _item_cache_zero(wd);
568    elm_smart_scroller_mirrored_set(wd->scr, rtl);
569 }
570
571 static void
572 _theme_hook(Evas_Object *obj)
573 {
574    Widget_Data *wd = elm_widget_data_get(obj);
575    Item_Block *itb;
576    if (!wd) return;
577    evas_event_freeze(evas_object_evas_get(wd->obj));
578    _item_cache_zero(wd);
579    _elm_widget_mirrored_reload(obj);
580    _mirrored_set(obj, elm_widget_mirrored_get(obj));
581    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
582                                        elm_widget_style_get(obj));
583    edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
584    wd->item_width = wd->item_height = 0;
585    wd->group_item_width = wd->group_item_height = 0;
586    wd->minw = wd->minh = wd->realminw = 0;
587    EINA_INLIST_FOREACH(wd->blocks, itb)
588      {
589         Eina_List *l;
590         Elm_Gen_Item *it;
591
592         if (itb->realized) _item_block_unrealize(itb);
593         EINA_LIST_FOREACH(itb->items, l, it)
594           it->item->mincalcd = EINA_FALSE;
595
596         itb->changed = EINA_TRUE;
597      }
598    if (wd->calc_job) ecore_job_del(wd->calc_job);
599    wd->calc_job = ecore_job_add(_calc_job, wd);
600    _sizing_eval(obj);
601    evas_event_thaw(evas_object_evas_get(wd->obj));
602    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
603 }
604
605 static void
606 _show_region_hook(void        *data,
607                   Evas_Object *obj)
608 {
609    Widget_Data *wd = elm_widget_data_get(data);
610    Evas_Coord x, y, w, h;
611    if (!wd) return;
612    elm_widget_show_region_get(obj, &x, &y, &w, &h);
613    //x & y are screen coordinates, Add with pan coordinates
614    x += wd->pan_x;
615    y += wd->pan_y;
616    elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
617 }
618
619 static void
620 _translate_hook(Evas_Object *obj)
621 {
622    evas_object_smart_callback_call(obj, "language,changed", NULL);
623 }
624
625 static void
626 _sizing_eval(Evas_Object *obj)
627 {
628    Widget_Data *wd = elm_widget_data_get(obj);
629    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
630    Evas_Coord vmw = 0, vmh = 0;
631    if (!wd) return;
632
633    evas_object_size_hint_min_get(wd->scr, &minw, NULL);
634    evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
635
636    edje_object_size_min_calc
637       (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
638
639    if (wd->mode == ELM_LIST_COMPRESS)
640      {
641         Evas_Coord vw, vh;
642
643         elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
644         if ((vw != 0) && (vw != wd->prev_viewport_w))
645           {
646              Item_Block *itb;
647
648              wd->prev_viewport_w = vw;
649              EINA_INLIST_FOREACH(wd->blocks, itb)
650                {
651                   itb->must_recalc = EINA_TRUE;
652                }
653              if (wd->calc_job) ecore_job_del(wd->calc_job);
654              wd->calc_job = ecore_job_add(_calc_job, wd);
655           }
656         minw = vmw;
657         minh = vmh;
658      }
659    else if (wd->mode == ELM_LIST_LIMIT)
660      {
661         maxw = -1;
662         minw = vmw + minw;
663      }
664    else
665      {
666         minw = vmw;
667         minh = vmh;
668      }
669
670    evas_object_size_hint_min_set(obj, minw, minh);
671    evas_object_size_hint_max_set(obj, maxw, maxh);
672 }
673
674 static void
675 _signal_emit_hook(Evas_Object *obj,
676                   const char  *emission,
677                   const char  *source)
678 {
679    Widget_Data *wd = elm_widget_data_get(obj);
680    edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
681                            emission, source);
682 }
683
684 static void
685 _item_highlight(Elm_Gen_Item *it)
686 {
687    const char *selectraise;
688    if ((it->wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
689        (!it->wd->highlight) ||
690        (it->generation < it->wd->generation) ||
691        (it->highlighted) || elm_widget_item_disabled_get(it) ||
692        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) || (it->item->mode_view) ||
693        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
694      return;
695    edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
696    if (it->edit_obj) edje_object_signal_emit(it->edit_obj, "elm,state,selected", "elm");
697    selectraise = edje_object_data_get(VIEW(it), "selectraise");
698    if ((selectraise) && (!strcmp(selectraise, "on")))
699      {
700         if (it->edit_obj) evas_object_raise(it->edit_obj);
701         else evas_object_raise(VIEW(it));
702         if ((it->item->group_item) && (it->item->group_item->realized))
703           evas_object_raise(it->item->VIEW(group_item));
704      }
705    it->highlighted = EINA_TRUE;
706 }
707
708 static void
709 _item_unhighlight(Elm_Gen_Item *it)
710 {
711    if ((it->generation < it->wd->generation) || (!it->highlighted)) return;
712    edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
713    if (it->edit_obj) edje_object_signal_emit(it->edit_obj, "elm,state,unselected", "elm");
714    if (!it->item->nostacking)
715      {
716        if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
717          {
718              if (it->edit_obj) evas_object_lower(it->edit_obj);
719              else evas_object_lower(VIEW(it));
720          }
721        else
722          {
723              if (it->edit_obj) evas_object_raise(it->edit_obj);
724              else evas_object_raise(VIEW(it));
725          }
726      }
727    it->highlighted = EINA_FALSE;
728 }
729
730 static void
731 _item_block_position_update(Eina_Inlist *list, int idx)
732 {
733    Item_Block *tmp;
734
735    EINA_INLIST_FOREACH(list, tmp)
736      {
737         tmp->position = idx++;
738         tmp->position_update = EINA_TRUE;
739      }
740 }
741
742 static void
743 _item_position_update(Eina_List *list, int idx)
744 {
745    Elm_Gen_Item *it;
746    Eina_List *l;
747
748    EINA_LIST_FOREACH(list, l, it)
749      {
750         it->position = idx++;
751         it->position_update = EINA_TRUE;
752      }
753 }
754
755 static void
756 _item_block_del(Elm_Gen_Item *it)
757 {
758    Eina_Inlist *il;
759    Item_Block *itb = it->item->block;
760
761    itb->items = eina_list_remove(itb->items, it);
762    itb->count--;
763    itb->changed = EINA_TRUE;
764    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
765    it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
766    if (itb->count < 1)
767      {
768         il = EINA_INLIST_GET(itb);
769         Item_Block *itbn = (Item_Block *)(il->next);
770         if (it->parent)
771           it->parent->item->items = eina_list_remove(it->parent->item->items, it);
772         else
773           {
774              _item_block_position_update(il->next, itb->position);
775              it->wd->blocks = eina_inlist_remove(it->wd->blocks, il);
776           }
777         free(itb);
778         if (itbn) itbn->changed = EINA_TRUE;
779      }
780    else
781      {
782         if (itb->count < itb->wd->max_items_per_block/2)
783           {
784              il = EINA_INLIST_GET(itb);
785              Item_Block *itbp = (Item_Block *)(il->prev);
786              Item_Block *itbn = (Item_Block *)(il->next);
787              if ((itbp) && ((itbp->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
788                {
789                   Elm_Gen_Item *it2;
790
791                   EINA_LIST_FREE(itb->items, it2)
792                     {
793                        it2->item->block = itbp;
794                        itbp->items = eina_list_append(itbp->items, it2);
795                        itbp->count++;
796                        itbp->changed = EINA_TRUE;
797                     }
798                   _item_block_position_update(EINA_INLIST_GET(itb)->next,
799                                               itb->position);
800                   it->wd->blocks = eina_inlist_remove(it->wd->blocks,
801                                                       EINA_INLIST_GET(itb));
802                   free(itb);
803                }
804              else if ((itbn) && ((itbn->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
805                {
806                   while (itb->items)
807                     {
808                        Eina_List *last = eina_list_last(itb->items);
809                        Elm_Gen_Item *it2 = last->data;
810
811                        it2->item->block = itbn;
812                        itb->items = eina_list_remove_list(itb->items, last);
813                        itbn->items = eina_list_prepend(itbn->items, it2);
814                        itbn->count++;
815                        itbn->changed = EINA_TRUE;
816                     }
817                   _item_block_position_update(EINA_INLIST_GET(itb)->next,
818                                               itb->position);
819                   it->wd->blocks =
820                     eina_inlist_remove(it->wd->blocks, EINA_INLIST_GET(itb));
821                   free(itb);
822                }
823           }
824      }
825 }
826
827 static void
828 _item_subitems_clear(Elm_Gen_Item *it)
829 {
830    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
831    Eina_List *tl = NULL, *l;
832    Elm_Object_Item *it2;
833
834    EINA_LIST_FOREACH(it->item->items, l, it2)
835      tl = eina_list_append(tl, it2);
836    EINA_LIST_FREE(tl, it2)
837      elm_object_item_del(it2);
838 }
839
840 static void
841 _item_del(Elm_Gen_Item *it)
842 {
843    Evas_Object *obj = WIDGET(it);
844
845    evas_event_freeze(evas_object_evas_get(obj));
846    elm_genlist_item_subitems_clear((Elm_Object_Item *)it);
847    if (it->wd->show_item == it) it->wd->show_item = NULL;
848    if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE);
849    if (it->item->decorate_mode_item_realized) _decorate_mode_item_unrealize(it);
850    if (it->item->block) _item_block_del(it);
851    if (it->item->queued)
852      it->wd->queue = eina_list_remove(it->wd->queue, it);
853    if (it->wd->anchor_item == it)
854      {
855         it->wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
856         if (!it->wd->anchor_item)
857           it->wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
858      }
859    if (it->wd->expanded_item == it) it->wd->expanded_item = NULL;
860    if (it->parent)
861      it->parent->item->items = eina_list_remove(it->parent->item->items, it);
862    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
863    _elm_genlist_item_del_serious(it);
864    elm_genlist_item_class_unref((Elm_Genlist_Item_Class *)it->itc);
865    evas_event_thaw(evas_object_evas_get(obj));
866    evas_event_thaw_eval(evas_object_evas_get(obj));
867 }
868
869 static void
870 _clear_cb(Widget_Data *wd)
871 {
872    wd->anchor_item = NULL;
873    while (wd->blocks)
874      {
875         Item_Block *itb = (Item_Block *)(wd->blocks);
876
877         wd->blocks = eina_inlist_remove(wd->blocks, wd->blocks);
878         if (itb->items) eina_list_free(itb->items);
879         free(itb);
880      }
881    if (wd->queue_idle_enterer)
882      {
883         ecore_idle_enterer_del(wd->queue_idle_enterer);
884         wd->queue_idle_enterer = NULL;
885      }
886    if (wd->must_recalc_idler)
887      {
888         ecore_idler_del(wd->must_recalc_idler);
889         wd->must_recalc_idler = NULL;
890      }
891    if (wd->queue) wd->queue = eina_list_free(wd->queue);
892    if (wd->reorder_move_animator)
893      {
894         ecore_animator_del(wd->reorder_move_animator);
895         wd->reorder_move_animator = NULL;
896      }
897    wd->show_item = NULL;
898    wd->reorder_old_pan_y = 0;
899 }
900
901 static void
902 _item_unselect(Elm_Gen_Item *it)
903 {
904    if ((it->generation < it->wd->generation) || (!it->selected)) return;
905    it->selected = EINA_FALSE;
906    it->wd->selected = eina_list_remove(it->wd->selected, it);
907    evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
908 }
909
910 static void
911 _mouse_move(void        *data,
912             Evas        *evas __UNUSED__,
913             Evas_Object *obj,
914             void        *event_info)
915 {
916    Elm_Gen_Item *it = data;
917    Evas_Event_Mouse_Move *ev = event_info;
918    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
919    Evas_Coord ox, oy, ow, oh, it_scrl_y, y_pos;
920
921    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
922      {
923         if (!it->wd->on_hold)
924           {
925              it->wd->on_hold = EINA_TRUE;
926              if ((!it->wd->wasselected) && (!it->flipped))
927                {
928                   _item_unhighlight(it);
929                   _item_unselect(it);
930                }
931           }
932      }
933    if (it->wd->multitouched)
934      {
935         it->wd->cur_x = ev->cur.canvas.x;
936         it->wd->cur_y = ev->cur.canvas.y;
937         return;
938      }
939    if ((it->dragging) && (it->down))
940      {
941         if (it->wd->movements == SWIPE_MOVES) it->wd->swipe = EINA_TRUE;
942         else
943           {
944              it->wd->history[it->wd->movements].x = ev->cur.canvas.x;
945              it->wd->history[it->wd->movements].y = ev->cur.canvas.y;
946              if (abs((it->wd->history[it->wd->movements].x -
947                       it->wd->history[0].x)) > 40)
948                it->wd->swipe = EINA_TRUE;
949              else
950                it->wd->movements++;
951           }
952         if (it->long_timer)
953           {
954              ecore_timer_del(it->long_timer);
955              it->long_timer = NULL;
956           }
957         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG, it);
958         return;
959      }
960    if ((!it->down) /* || (it->wd->on_hold)*/ || (it->wd->longpressed))
961      {
962         if (it->long_timer)
963           {
964              ecore_timer_del(it->long_timer);
965              it->long_timer = NULL;
966           }
967         if ((it->wd->reorder_mode) && (it->wd->reorder_it))
968           {
969              evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
970              it_scrl_y = ev->cur.canvas.y - it->wd->reorder_it->dy;
971
972              if (!it->wd->reorder_start_y)
973                it->wd->reorder_start_y = it->item->block->y + it->y;
974
975              if (it_scrl_y < oy)
976                y_pos = oy;
977              else if (it_scrl_y + it->wd->reorder_it->item->h > oy + oh)
978                y_pos = oy + oh - it->wd->reorder_it->item->h;
979              else
980                y_pos = it_scrl_y;
981
982              if (it->edit_obj)
983                _item_position(it, it->edit_obj, it->item->scrl_x, y_pos);
984              else
985              _item_position(it, VIEW(it), it->item->scrl_x, y_pos);
986
987              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
988              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
989           }
990         return;
991      }
992    if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
993      elm_coords_finger_size_adjust(1, &minw, 1, &minh);
994    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
995    x = ev->cur.canvas.x - x;
996    y = ev->cur.canvas.y - y;
997    dx = x - it->dx;
998    adx = dx;
999    if (adx < 0) adx = -dx;
1000    dy = y - it->dy;
1001    ady = dy;
1002    if (ady < 0) ady = -dy;
1003    minw /= 2;
1004    minh /= 2;
1005    if ((adx > minw) || (ady > minh))
1006      {
1007         it->dragging = EINA_TRUE;
1008         if (it->long_timer)
1009           {
1010              ecore_timer_del(it->long_timer);
1011              it->long_timer = NULL;
1012           }
1013         if (!it->wd->wasselected)
1014           {
1015              _item_unhighlight(it);
1016              _item_unselect(it);
1017           }
1018         if (dy < 0)
1019           {
1020              if (ady > adx)
1021                evas_object_smart_callback_call(WIDGET(it),
1022                                                SIG_DRAG_START_UP, it);
1023              else
1024                {
1025                   if (dx < 0)
1026                     evas_object_smart_callback_call(WIDGET(it),
1027                                                     SIG_DRAG_START_LEFT, it);
1028                   else
1029                     evas_object_smart_callback_call(WIDGET(it),
1030                                                     SIG_DRAG_START_RIGHT, it);
1031                }
1032           }
1033         else
1034           {
1035              if (ady > adx)
1036                evas_object_smart_callback_call(WIDGET(it),
1037                                                SIG_DRAG_START_DOWN, it);
1038              else
1039                {
1040                   if (dx < 0)
1041                     evas_object_smart_callback_call(WIDGET(it),
1042                                                     SIG_DRAG_START_LEFT, it);
1043                   else
1044                     evas_object_smart_callback_call(WIDGET(it),
1045                                                     SIG_DRAG_START_RIGHT, it);
1046                }
1047           }
1048      }
1049 }
1050
1051 static Eina_Bool
1052 _long_press(void *data)
1053 {
1054    Elm_Gen_Item *it = data, *it_tmp;
1055    Eina_List *list, *l;
1056
1057    it->long_timer = NULL;
1058    if (elm_widget_item_disabled_get(it) || (it->dragging) ||
1059        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
1060      return ECORE_CALLBACK_CANCEL;
1061    it->wd->longpressed = EINA_TRUE;
1062    evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
1063    if ((it->wd->reorder_mode) && (!it->group))
1064      {
1065         it->wd->reorder_it = it;
1066         it->wd->reorder_start_y = 0;
1067         if (it->edit_obj)
1068           evas_object_raise(it->edit_obj);
1069         else
1070           evas_object_raise(VIEW(it));
1071
1072         elm_smart_scroller_hold_set(it->wd->scr, EINA_TRUE);
1073         elm_smart_scroller_bounce_allow_set(it->wd->scr, EINA_FALSE, EINA_FALSE);
1074
1075         list = elm_genlist_realized_items_get(it->wd->obj);
1076         EINA_LIST_FOREACH(list, l, it_tmp)
1077           {
1078              if (it != it_tmp) _item_unselect(it_tmp);
1079           }
1080         if (elm_genlist_item_expanded_get((Elm_Object_Item *)it))
1081           {
1082              elm_genlist_item_expanded_set((Elm_Object_Item *)it, EINA_FALSE);
1083              return ECORE_CALLBACK_RENEW;
1084           }
1085
1086         if (!it->wd->decorate_mode)
1087           edje_object_signal_emit(VIEW(it), "elm,state,reorder,enabled", "elm");
1088      }
1089    return ECORE_CALLBACK_CANCEL;
1090 }
1091
1092 static void
1093 _swipe(Elm_Gen_Item *it)
1094 {
1095    int i, sum = 0;
1096
1097    if (!it) return;
1098    if ((it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY) ||
1099        elm_widget_item_disabled_get(it)) return;
1100    it->wd->swipe = EINA_FALSE;
1101    for (i = 0; i < it->wd->movements; i++)
1102      {
1103         sum += it->wd->history[i].x;
1104         if (abs(it->wd->history[0].y - it->wd->history[i].y) > 10) return;
1105      }
1106
1107    sum /= it->wd->movements;
1108    if (abs(sum - it->wd->history[0].x) <= 10) return;
1109    evas_object_smart_callback_call(WIDGET(it), SIG_SWIPE, it);
1110 }
1111
1112 static Eina_Bool
1113 _swipe_cancel(void *data)
1114 {
1115    Elm_Gen_Item *it = data;
1116
1117    if (!it) return ECORE_CALLBACK_CANCEL;
1118    it->wd->swipe = EINA_FALSE;
1119    it->wd->movements = 0;
1120    return ECORE_CALLBACK_RENEW;
1121 }
1122
1123 static Eina_Bool
1124 _multi_cancel(void *data)
1125 {
1126    Widget_Data *wd = data;
1127
1128    if (!wd) return ECORE_CALLBACK_CANCEL;
1129    wd->multi_timeout = EINA_TRUE;
1130    return ECORE_CALLBACK_RENEW;
1131 }
1132
1133 static void
1134 _multi_touch_gesture_eval(void *data)
1135 {
1136    Elm_Gen_Item *it = data;
1137
1138    it->wd->multitouched = EINA_FALSE;
1139    if (it->wd->multi_timer)
1140      {
1141         ecore_timer_del(it->wd->multi_timer);
1142         it->wd->multi_timer = NULL;
1143      }
1144    if (it->wd->multi_timeout)
1145      {
1146         it->wd->multi_timeout = EINA_FALSE;
1147         return;
1148      }
1149
1150    Evas_Coord minw = 0, minh = 0;
1151    Evas_Coord off_x, off_y, off_mx, off_my;
1152
1153    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1154    off_x = abs(it->wd->cur_x - it->wd->prev_x);
1155    off_y = abs(it->wd->cur_y - it->wd->prev_y);
1156    off_mx = abs(it->wd->cur_mx - it->wd->prev_mx);
1157    off_my = abs(it->wd->cur_my - it->wd->prev_my);
1158
1159    if (((off_x > minw) || (off_y > minh)) && ((off_mx > minw) || (off_my > minh)))
1160      {
1161         if ((off_x + off_mx) > (off_y + off_my))
1162           {
1163              if ((it->wd->cur_x > it->wd->prev_x) && (it->wd->cur_mx > it->wd->prev_mx))
1164                evas_object_smart_callback_call(WIDGET(it),
1165                                                SIG_MULTI_SWIPE_RIGHT, it);
1166              else if ((it->wd->cur_x < it->wd->prev_x) && (it->wd->cur_mx < it->wd->prev_mx))
1167                evas_object_smart_callback_call(WIDGET(it),
1168                                                SIG_MULTI_SWIPE_LEFT, it);
1169              else if (abs(it->wd->cur_x - it->wd->cur_mx) > abs(it->wd->prev_x - it->wd->prev_mx))
1170                evas_object_smart_callback_call(WIDGET(it),
1171                                                SIG_MULTI_PINCH_OUT, it);
1172              else
1173                evas_object_smart_callback_call(WIDGET(it),
1174                                                SIG_MULTI_PINCH_IN, it);
1175           }
1176         else
1177           {
1178              if ((it->wd->cur_y > it->wd->prev_y) && (it->wd->cur_my > it->wd->prev_my))
1179                evas_object_smart_callback_call(WIDGET(it),
1180                                                SIG_MULTI_SWIPE_DOWN, it);
1181              else if ((it->wd->cur_y < it->wd->prev_y) && (it->wd->cur_my < it->wd->prev_my))
1182                evas_object_smart_callback_call(WIDGET(it),
1183                                                SIG_MULTI_SWIPE_UP, it);
1184              else if (abs(it->wd->cur_y - it->wd->cur_my) > abs(it->wd->prev_y - it->wd->prev_my))
1185                evas_object_smart_callback_call(WIDGET(it),
1186                                                SIG_MULTI_PINCH_OUT, it);
1187              else
1188                evas_object_smart_callback_call(WIDGET(it),
1189                                                SIG_MULTI_PINCH_IN, it);
1190           }
1191      }
1192    it->wd->multi_timeout = EINA_FALSE;
1193 }
1194
1195 static void
1196 _multi_down(void        *data,
1197             Evas        *evas __UNUSED__,
1198             Evas_Object *obj __UNUSED__,
1199             void        *event_info)
1200 {
1201    Elm_Gen_Item *it = data;
1202    Evas_Event_Multi_Down *ev = event_info;
1203
1204    if ((it->wd->multi_device != 0) || (it->wd->multitouched) || (it->wd->multi_timeout)) return;
1205    it->wd->multi_device = ev->device;
1206    it->wd->multi_down = EINA_TRUE;
1207    it->wd->multitouched = EINA_TRUE;
1208    it->wd->prev_mx = ev->canvas.x;
1209    it->wd->prev_my = ev->canvas.y;
1210    if (!it->wd->wasselected)
1211      {
1212         _item_unhighlight(it);
1213         _item_unselect(it);
1214      }
1215    it->wd->wasselected = EINA_FALSE;
1216    it->wd->longpressed = EINA_FALSE;
1217    if (it->long_timer)
1218      {
1219         ecore_timer_del(it->long_timer);
1220         it->long_timer = NULL;
1221      }
1222    if (it->dragging)
1223      {
1224         it->dragging = EINA_FALSE;
1225         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1226      }
1227    if (it->item->swipe_timer)
1228      {
1229         ecore_timer_del(it->item->swipe_timer);
1230         it->item->swipe_timer = NULL;
1231      }
1232    if (it->wd->on_hold)
1233      {
1234         it->wd->swipe = EINA_FALSE;
1235         it->wd->movements = 0;
1236         it->wd->on_hold = EINA_FALSE;
1237      }
1238 }
1239
1240 static void
1241 _multi_up(void        *data,
1242           Evas        *evas __UNUSED__,
1243           Evas_Object *obj __UNUSED__,
1244           void        *event_info)
1245 {
1246    Elm_Gen_Item *it = data;
1247    Evas_Event_Multi_Up *ev = event_info;
1248
1249    if (it->wd->multi_device != ev->device) return;
1250    it->wd->multi_device = 0;
1251    it->wd->multi_down = EINA_FALSE;
1252    if (it->wd->mouse_down) return;
1253    _multi_touch_gesture_eval(data);
1254 }
1255
1256 static void
1257 _multi_move(void        *data,
1258             Evas        *evas __UNUSED__,
1259             Evas_Object *obj __UNUSED__,
1260             void        *event_info)
1261 {
1262    Elm_Gen_Item *it = data;
1263    Evas_Event_Multi_Move *ev = event_info;
1264
1265    if (it->wd->multi_device != ev->device) return;
1266    it->wd->cur_mx = ev->cur.canvas.x;
1267    it->wd->cur_my = ev->cur.canvas.y;
1268 }
1269
1270 static void
1271 _mouse_down(void        *data,
1272             Evas        *evas __UNUSED__,
1273             Evas_Object *obj,
1274             void        *event_info)
1275 {
1276    Elm_Gen_Item *it = data;
1277    Evas_Event_Mouse_Down *ev = event_info;
1278    Evas_Coord x, y;
1279
1280    if (ev->button != 1) return;
1281    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
1282      {
1283         it->wd->on_hold = EINA_TRUE;
1284      }
1285
1286    it->down = EINA_TRUE;
1287    it->dragging = EINA_FALSE;
1288    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1289    it->dx = ev->canvas.x - x;
1290    it->dy = ev->canvas.y - y;
1291    it->wd->mouse_down = EINA_TRUE;
1292    if (!it->wd->multitouched)
1293      {
1294         it->wd->prev_x = ev->canvas.x;
1295         it->wd->prev_y = ev->canvas.y;
1296         it->wd->multi_timeout = EINA_FALSE;
1297         if (it->wd->multi_timer) ecore_timer_del(it->wd->multi_timer);
1298         it->wd->multi_timer = ecore_timer_add(1, _multi_cancel, it->wd);
1299      }
1300    it->wd->longpressed = EINA_FALSE;
1301    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1302    else it->wd->on_hold = EINA_FALSE;
1303    if (it->wd->on_hold) return;
1304    it->wd->wasselected = it->selected;
1305    _item_highlight(it);
1306    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1307      if ((!elm_widget_item_disabled_get(it)) &&
1308          (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
1309        {
1310           evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
1311           evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
1312        }
1313    if (it->long_timer) ecore_timer_del(it->long_timer);
1314    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
1315    it->item->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
1316    if (it->realized)
1317      it->long_timer = ecore_timer_add(it->wd->longpress_timeout, _long_press,
1318                                       it);
1319    else
1320      it->long_timer = NULL;
1321    it->wd->swipe = EINA_FALSE;
1322    it->wd->movements = 0;
1323 }
1324
1325 static void
1326 _mouse_up(void        *data,
1327           Evas        *evas __UNUSED__,
1328           Evas_Object *obj __UNUSED__,
1329           void        *event_info)
1330 {
1331    Elm_Gen_Item *it = data;
1332    Evas_Event_Mouse_Up *ev = event_info;
1333    Eina_Bool dragged = EINA_FALSE;
1334
1335    if (ev->button != 1) return;
1336    it->down = EINA_FALSE;
1337    it->wd->mouse_down = EINA_FALSE;
1338    if (it->wd->multitouched)
1339      {
1340         if ((!it->wd->multi) && (!it->selected) && (it->highlighted)) _item_unhighlight(it);
1341         if (it->wd->multi_down) return;
1342         _multi_touch_gesture_eval(data);
1343         return;
1344      }
1345    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1346    else it->wd->on_hold = EINA_FALSE;
1347    if (it->long_timer)
1348      {
1349         ecore_timer_del(it->long_timer);
1350         it->long_timer = NULL;
1351      }
1352    if (it->dragging)
1353      {
1354         it->dragging = EINA_FALSE;
1355         evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1356         dragged = 1;
1357      }
1358    if (it->item->swipe_timer)
1359      {
1360         ecore_timer_del(it->item->swipe_timer);
1361         it->item->swipe_timer = NULL;
1362      }
1363    if (it->wd->multi_timer)
1364      {
1365         ecore_timer_del(it->wd->multi_timer);
1366         it->wd->multi_timer = NULL;
1367         it->wd->multi_timeout = EINA_FALSE;
1368      }
1369    if (it->wd->on_hold)
1370      {
1371         if (it->wd->swipe) _swipe(data);
1372         it->wd->longpressed = EINA_FALSE;
1373         it->wd->on_hold = EINA_FALSE;
1374         return;
1375      }
1376    if ((it->wd->reorder_mode) && (it->wd->reorder_it))
1377      {
1378         Evas_Coord it_scrl_y = ev->canvas.y - it->wd->reorder_it->dy;
1379
1380         if (it->wd->reorder_rel && (it->wd->reorder_it->parent == it->wd->reorder_rel->parent))
1381           {
1382              if (it_scrl_y <= it->wd->reorder_rel->item->scrl_y)
1383                _item_move_before(it->wd->reorder_it, it->wd->reorder_rel);
1384              else
1385                _item_move_after(it->wd->reorder_it, it->wd->reorder_rel);
1386           }
1387         else
1388           {
1389              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
1390              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
1391           }
1392         edje_object_signal_emit(VIEW(it), "elm,state,reorder,disabled", "elm");
1393         it->wd->reorder_it = it->wd->reorder_rel = NULL;
1394         elm_smart_scroller_hold_set(it->wd->scr, EINA_FALSE);
1395         elm_smart_scroller_bounce_allow_set(it->wd->scr, it->wd->h_bounce, it->wd->v_bounce);
1396      }
1397    if (it->wd->longpressed)
1398      {
1399         it->wd->longpressed = EINA_FALSE;
1400         if ((!it->wd->wasselected) && (!it->flipped))
1401           {
1402              _item_unhighlight(it);
1403              _item_unselect(it);
1404           }
1405         it->wd->wasselected = EINA_FALSE;
1406         return;
1407      }
1408    if (dragged)
1409      {
1410         if (it->want_unrealize)
1411           {
1412              _elm_genlist_item_unrealize(it, EINA_FALSE);
1413              if (it->item->block->want_unrealize)
1414                _item_block_unrealize(it->item->block);
1415           }
1416      }
1417    if (elm_widget_item_disabled_get(it) || (dragged) ||
1418        (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
1419      return;
1420    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1421    if (it->wd->multi)
1422      {
1423         if (!it->selected)
1424           {
1425              _item_highlight(it);
1426              it->sel_cb(it);
1427           }
1428         else
1429           {
1430              _item_unhighlight(it);
1431              _item_unselect(it);
1432           }
1433      }
1434    else
1435      {
1436         if (!it->selected)
1437           {
1438              Widget_Data *wd = it->wd;
1439              if (wd)
1440                {
1441                   while (wd->selected)
1442                     {
1443                        _item_unhighlight(wd->selected->data);
1444                        _item_unselect(wd->selected->data);
1445                     }
1446                }
1447           }
1448         else
1449           {
1450              const Eina_List *l, *l_next;
1451              Elm_Gen_Item *it2;
1452
1453              EINA_LIST_FOREACH_SAFE(it->wd->selected, l, l_next, it2)
1454                if (it2 != it)
1455                   {
1456                      _item_unhighlight(it2);
1457                      _item_unselect(it2);
1458                   }
1459              //_item_highlight(it);
1460              //_item_select(it);
1461           }
1462         _item_highlight(it);
1463         it->sel_cb(it);
1464      }
1465 }
1466
1467 static void
1468 _item_mouse_callbacks_add(Elm_Gen_Item *it, Evas_Object *view)
1469 {
1470    evas_object_event_callback_add(view, EVAS_CALLBACK_MOUSE_DOWN,
1471                                   _mouse_down, it);
1472    evas_object_event_callback_add(view, EVAS_CALLBACK_MOUSE_UP,
1473                                   _mouse_up, it);
1474    evas_object_event_callback_add(view, EVAS_CALLBACK_MOUSE_MOVE,
1475                                   _mouse_move, it);
1476    evas_object_event_callback_add(view, EVAS_CALLBACK_MULTI_DOWN,
1477                                   _multi_down, it);
1478    evas_object_event_callback_add(view, EVAS_CALLBACK_MULTI_UP,
1479                                   _multi_up, it);
1480    evas_object_event_callback_add(view, EVAS_CALLBACK_MULTI_MOVE,
1481                                   _multi_move, it);
1482 }
1483
1484 static void
1485 _item_mouse_callbacks_del(Elm_Gen_Item *it, Evas_Object *view)
1486 {
1487    evas_object_event_callback_del_full(view, EVAS_CALLBACK_MOUSE_DOWN,
1488                                        _mouse_down, it);
1489    evas_object_event_callback_del_full(view, EVAS_CALLBACK_MOUSE_UP,
1490                                        _mouse_up, it);
1491    evas_object_event_callback_del_full(view, EVAS_CALLBACK_MOUSE_MOVE,
1492                                        _mouse_move, it);
1493    evas_object_event_callback_del_full(view, EVAS_CALLBACK_MULTI_DOWN,
1494                                        _multi_down, it);
1495    evas_object_event_callback_del_full(view, EVAS_CALLBACK_MULTI_UP,
1496                                        _multi_up, it);
1497    evas_object_event_callback_del_full(view, EVAS_CALLBACK_MULTI_MOVE,
1498                                        _multi_move, it);
1499 }
1500
1501 static void
1502 _signal_expand_toggle(void        *data,
1503                       Evas_Object *obj __UNUSED__,
1504                       const char  *emission __UNUSED__,
1505                       const char  *source __UNUSED__)
1506 {
1507    Elm_Gen_Item *it = data;
1508
1509    if (it->item->expanded)
1510      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1511    else
1512      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1513 }
1514
1515 static void
1516 _signal_expand(void        *data,
1517                Evas_Object *obj __UNUSED__,
1518                const char  *emission __UNUSED__,
1519                const char  *source __UNUSED__)
1520 {
1521    Elm_Gen_Item *it = data;
1522
1523    if (!it->item->expanded)
1524      evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1525 }
1526
1527 static void
1528 _signal_contract(void        *data,
1529                  Evas_Object *obj __UNUSED__,
1530                  const char  *emission __UNUSED__,
1531                  const char  *source __UNUSED__)
1532 {
1533    Elm_Gen_Item *it = data;
1534
1535    if (it->item->expanded)
1536      evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1537 }
1538
1539 static Eina_Bool
1540 _scr_hold_timer_cb(void *data)
1541 {
1542    if (!data) return ECORE_CALLBACK_CANCEL;
1543    Widget_Data *wd = data;
1544    elm_smart_scroller_hold_set(wd->scr, EINA_FALSE);
1545    wd->scr_hold_timer = NULL;
1546    return ECORE_CALLBACK_CANCEL;
1547 }
1548
1549 static void
1550 _mode_finished_signal_cb(void        *data,
1551                          Evas_Object *obj,
1552                          const char  *emission __UNUSED__,
1553                          const char  *source __UNUSED__)
1554 {
1555    if (!data) return;
1556    if (!obj) return;
1557    Elm_Gen_Item *it = data;
1558    if ((it->generation < it->wd->generation) || (!it->realized) || (!it->item->mode_view)) return;
1559    char buf[1024];
1560    Evas *te = evas_object_evas_get(obj);
1561
1562    evas_event_freeze(te);
1563    it->item->nocache_once = EINA_FALSE;
1564    _mode_item_unrealize(it);
1565    if (it->item->group_item)
1566      evas_object_raise(it->item->VIEW(group_item));
1567    snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished", it->wd->decorate_type);
1568    edje_object_signal_callback_del_full(obj, buf, "elm", _mode_finished_signal_cb, it);
1569    evas_event_thaw(te);
1570    evas_event_thaw_eval(te);
1571 }
1572
1573 static void
1574 _item_cache_clean(Widget_Data *wd)
1575 {
1576    evas_event_freeze(evas_object_evas_get(wd->obj));
1577    while ((wd->item_cache) && (wd->item_cache_count > wd->item_cache_max))
1578      {
1579         Item_Cache *itc;
1580
1581         itc = EINA_INLIST_CONTAINER_GET(wd->item_cache->last, Item_Cache);
1582         wd->item_cache = eina_inlist_remove(wd->item_cache,
1583                                             wd->item_cache->last);
1584         wd->item_cache_count--;
1585         if (itc->spacer) evas_object_del(itc->spacer);
1586         if (itc->base_view) evas_object_del(itc->base_view);
1587         eina_stringshare_del(itc->item_style);
1588         free(itc);
1589      }
1590    evas_event_thaw(evas_object_evas_get(wd->obj));
1591    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
1592 }
1593
1594 static void
1595 _item_cache_zero(Widget_Data *wd)
1596 {
1597    int pmax = wd->item_cache_max;
1598    wd->item_cache_max = 0;
1599    _item_cache_clean(wd);
1600    wd->item_cache_max = pmax;
1601 }
1602
1603 static void
1604 _item_cache_add(Elm_Gen_Item *it)
1605 {
1606    Item_Cache *itc;
1607
1608    evas_event_freeze(evas_object_evas_get(it->wd->obj));
1609    if (it->wd->item_cache_max <= 0)
1610      {
1611         evas_object_del(VIEW(it));
1612         VIEW(it) = NULL;
1613         if (it->spacer)
1614           {
1615              evas_object_del(it->spacer);
1616              it->spacer = NULL;
1617           }
1618         evas_event_thaw(evas_object_evas_get(it->wd->obj));
1619         evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1620         return;
1621      }
1622
1623    it->wd->item_cache_count++;
1624    itc = calloc(1, sizeof(Item_Cache));
1625    if (!itc)
1626      {
1627         evas_event_thaw(evas_object_evas_get(it->wd->obj));
1628         evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1629         return;
1630      }
1631    it->wd->item_cache = eina_inlist_prepend(it->wd->item_cache,
1632                                             EINA_INLIST_GET(itc));
1633    itc->spacer = it->spacer;
1634    it->spacer = NULL;
1635    itc->base_view = VIEW(it);
1636    VIEW(it) = NULL;
1637    edje_object_signal_emit(itc->base_view, "elm,state,unselected", "elm");
1638    evas_object_hide(itc->base_view);
1639    evas_object_move(itc->base_view, -9999, -9999);
1640    itc->item_style = eina_stringshare_add(it->itc->item_style);
1641    if (it->item->type & ELM_GENLIST_ITEM_TREE) itc->tree = 1;
1642    itc->selected = it->selected;
1643    itc->disabled = elm_widget_item_disabled_get(it);
1644    itc->expanded = it->item->expanded;
1645    if (it->long_timer)
1646      {
1647         ecore_timer_del(it->long_timer);
1648         it->long_timer = NULL;
1649      }
1650    if (it->item->swipe_timer)
1651      {
1652         ecore_timer_del(it->item->swipe_timer);
1653         it->item->swipe_timer = NULL;
1654      }
1655    // FIXME: other callbacks?
1656    edje_object_signal_callback_del_full(itc->base_view,
1657                                         "elm,action,expand,toggle",
1658                                         "elm", _signal_expand_toggle, it);
1659    edje_object_signal_callback_del_full(itc->base_view, "elm,action,expand",
1660                                         "elm",
1661                                         _signal_expand, it);
1662    edje_object_signal_callback_del_full(itc->base_view, "elm,action,contract",
1663                                         "elm", _signal_contract, it);
1664    _item_mouse_callbacks_del(it, itc->base_view);
1665    _item_cache_clean(it->wd);
1666    evas_event_thaw(evas_object_evas_get(it->wd->obj));
1667    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1668 }
1669
1670 static Item_Cache *
1671 _item_cache_find(Elm_Gen_Item *it)
1672 {
1673    Item_Cache *itc;
1674    Eina_Bool tree = 0;
1675
1676    if (it->item->type & ELM_GENLIST_ITEM_TREE) tree = 1;
1677    EINA_INLIST_FOREACH(it->wd->item_cache, itc)
1678      {
1679         if ((itc->selected) || (itc->disabled) || (itc->expanded))
1680           continue;
1681         if ((itc->tree == tree) &&
1682             (((!it->itc->item_style) && (!itc->item_style)) ||
1683              (it->itc->item_style && itc->item_style &&
1684             (!strcmp(it->itc->item_style, itc->item_style)))))
1685           {
1686              it->wd->item_cache = eina_inlist_remove(it->wd->item_cache,
1687                                                      EINA_INLIST_GET(itc));
1688              it->wd->item_cache_count--;
1689              return itc;
1690           }
1691      }
1692    return NULL;
1693 }
1694
1695 static void
1696 _elm_genlist_item_index_update(Elm_Gen_Item *it)
1697 {
1698    if (it->position_update || it->item->block->position_update)
1699      {
1700         evas_object_smart_callback_call(WIDGET(it), SIG_INDEX_UPDATE, it);
1701         it->position_update = EINA_FALSE;
1702      }
1703 }
1704
1705 static void
1706 _elm_genlist_item_odd_even_update(Elm_Gen_Item *it)
1707 {
1708    if (!it->item->nostacking)
1709      {
1710         if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
1711           {
1712              if (it->edit_obj) evas_object_lower(it->edit_obj);
1713              else evas_object_lower(VIEW(it));
1714           }
1715         else
1716           {
1717              if (it->edit_obj) evas_object_raise(it->edit_obj);
1718              else evas_object_raise(VIEW(it));
1719           }
1720      }
1721
1722    if (it->item->order_num_in & 0x1)
1723      {
1724         edje_object_signal_emit(VIEW(it), "elm,state,odd", "elm");
1725         if (it->edit_obj) edje_object_signal_emit(it->edit_obj, "elm,state,odd", "elm");
1726      }
1727    else
1728      {
1729         edje_object_signal_emit(VIEW(it), "elm,state,even", "elm");
1730         if (it->edit_obj) edje_object_signal_emit(it->edit_obj, "elm,state,even", "elm");
1731      }
1732 }
1733
1734 static void
1735 _elm_genlist_item_state_update(Elm_Gen_Item *it, Item_Cache *itc)
1736 {
1737    if (itc)
1738      {
1739         if (it->selected != itc->selected)
1740           {
1741              if (it->selected)
1742                edje_object_signal_emit(VIEW(it),
1743                                        "elm,state,selected", "elm");
1744
1745              if (it->edit_obj)
1746                edje_object_signal_emit(it->edit_obj,
1747                                        "elm,state,selected", "elm");
1748           }
1749         if (elm_widget_item_disabled_get(it) != itc->disabled)
1750           {
1751              if (elm_widget_item_disabled_get(it))
1752                edje_object_signal_emit(VIEW(it),
1753                                        "elm,state,disabled", "elm");
1754              if (it->edit_obj)
1755                edje_object_signal_emit(it->edit_obj,
1756                                        "elm,state,disabled", "elm");
1757           }
1758         if (it->item->expanded != itc->expanded)
1759           {
1760              if (it->item->expanded)
1761                edje_object_signal_emit(VIEW(it),
1762                                        "elm,state,expanded", "elm");
1763              if (it->edit_obj)
1764                edje_object_signal_emit(it->edit_obj,
1765                                        "elm,state,expanded", "elm");
1766           }
1767      }
1768    else
1769      {
1770         if (it->selected)
1771           {
1772              edje_object_signal_emit(VIEW(it),
1773                                      "elm,state,selected", "elm");
1774              if (it->edit_obj)
1775                edje_object_signal_emit(it->edit_obj,
1776                                        "elm,state,selected", "elm");
1777           }
1778
1779         if (elm_widget_item_disabled_get(it))
1780           {
1781              edje_object_signal_emit(VIEW(it),
1782                                      "elm,state,disabled", "elm");
1783              if (it->edit_obj)
1784                edje_object_signal_emit(it->edit_obj,
1785                                        "elm,state,disabled", "elm");
1786           }
1787         if (it->item->expanded)
1788           {
1789              edje_object_signal_emit(VIEW(it),
1790                                      "elm,state,expanded", "elm");
1791              if (it->edit_obj)
1792                edje_object_signal_emit(it->edit_obj,
1793                                        "elm,state,expanded", "elm");
1794           }
1795      }
1796 }
1797
1798 static void
1799 _item_cache_free(Item_Cache *itc)
1800 {
1801    if (itc->spacer) evas_object_del(itc->spacer);
1802    if (itc->base_view) evas_object_del(itc->base_view);
1803    eina_stringshare_del(itc->item_style);
1804    free(itc);
1805 }
1806
1807 static void
1808 _item_text_realize(Elm_Gen_Item *it,
1809                    Evas_Object *target,
1810                    Eina_List **source,
1811                    const char *parts)
1812 {
1813    if (it->itc->func.text_get)
1814      {
1815         const Eina_List *l;
1816         const char *key;
1817
1818         *source = elm_widget_stringlist_get(edje_object_data_get(target, "texts"));
1819         EINA_LIST_FOREACH(*source, l, key)
1820           {
1821              if (parts && fnmatch(parts, key, FNM_PERIOD))
1822                continue;
1823
1824              char *s = it->itc->func.text_get
1825                 ((void *)it->base.data, WIDGET(it), key);
1826
1827              if (s)
1828                {
1829                   edje_object_part_text_set(target, key, s);
1830                   free(s);
1831                }
1832              else
1833                {
1834                   edje_object_part_text_set(target, key, "");
1835                }
1836           }
1837      }
1838 }
1839
1840 static Eina_List *
1841 _item_content_unrealize(Elm_Gen_Item *it,
1842                         Evas_Object *target,
1843                         Eina_List **source,
1844                         const char *parts)
1845 {
1846    Eina_List *res = it->content_objs;
1847
1848    if (it->itc->func.content_get)
1849      {
1850         const Eina_List *l;
1851         const char *key;
1852         Evas_Object *ic = NULL;
1853
1854         EINA_LIST_FOREACH(*source, l, key)
1855           {
1856              if (parts && fnmatch(parts, key, FNM_PERIOD))
1857                continue;
1858
1859              ic = edje_object_part_swallow_get(target, key);
1860              if (ic)
1861                {
1862                   res = eina_list_remove(res, ic);
1863                   edje_object_part_unswallow(target, ic);
1864                   evas_object_del(ic);
1865                }
1866           }
1867      }
1868
1869    return res;
1870 }
1871
1872 static Eina_List *
1873 _item_content_realize(Elm_Gen_Item *it,
1874                       Evas_Object *target,
1875                       Eina_List **source,
1876                       const char *parts)
1877 {
1878    Eina_List *res = NULL;
1879
1880    if (it->itc->func.content_get)
1881      {
1882         const Eina_List *l;
1883         const char *key;
1884         Evas_Object *ic = NULL;
1885
1886         *source = elm_widget_stringlist_get(edje_object_data_get(target, "contents"));
1887
1888         if (parts && (eina_list_count(*source) != eina_list_count(it->content_objs)))
1889           res = it->content_objs;
1890
1891         EINA_LIST_FOREACH(*source, l, key)
1892           {
1893              if (parts && fnmatch(parts, key, FNM_PERIOD))
1894                continue;
1895
1896              if (it->itc->func.content_get)
1897                ic = it->itc->func.content_get
1898                   ((void *)it->base.data, WIDGET(it), key);
1899              if (ic)
1900                {
1901                   res = eina_list_append(res, ic);
1902                   edje_object_part_swallow(target, key, ic);
1903                   evas_object_show(ic);
1904                   elm_widget_sub_object_add(WIDGET(it), ic);
1905                   if (elm_widget_item_disabled_get(it))
1906                     elm_widget_disabled_set(ic, EINA_TRUE);
1907                }
1908           }
1909      }
1910
1911    return res;
1912 }
1913
1914 static void
1915 _item_state_realize(Elm_Gen_Item *it,
1916                     Evas_Object *target,
1917                     Eina_List **source,
1918                     const char *parts)
1919 {
1920    if (it->itc->func.state_get)
1921      {
1922         const Eina_List *l;
1923         const char *key;
1924         char buf[4096];
1925
1926         *source = elm_widget_stringlist_get(edje_object_data_get(target, "states"));
1927         EINA_LIST_FOREACH(*source, l, key)
1928           {
1929              if (parts && fnmatch(parts, key, FNM_PERIOD))
1930                continue;
1931
1932              Eina_Bool on = it->itc->func.state_get
1933                 ((void *)it->base.data, WIDGET(it), key);
1934
1935              if (on)
1936                {
1937                   snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
1938                   edje_object_signal_emit(target, buf, "elm");
1939                }
1940              else
1941                {
1942                   snprintf(buf, sizeof(buf), "elm,state,%s,passive", key);
1943                   edje_object_signal_emit(target, buf, "elm");
1944                }
1945           }
1946      }
1947 }
1948
1949 static Eina_List *
1950 _item_flips_realize(Elm_Gen_Item *it,
1951                     Evas_Object *target,
1952                     Eina_List **source)
1953 {
1954    Eina_List *res = NULL;
1955
1956    if (it->itc->func.content_get)
1957      {
1958         const Eina_List *l;
1959         const char *key;
1960         Evas_Object *ic = NULL;
1961         Eina_List *cons = NULL;
1962         cons = elm_widget_stringlist_get(edje_object_data_get(target, "flips"));
1963
1964         EINA_LIST_FOREACH(cons, l, key)
1965           {
1966              if (it->itc->func.content_get)
1967                ic = it->itc->func.content_get
1968                   ((void *)it->base.data, WIDGET(it), key);
1969              if (ic)
1970                {
1971                   res = eina_list_append(res, ic);
1972                   edje_object_part_swallow(target, key, ic);
1973                   evas_object_show(ic);
1974                   elm_widget_sub_object_add(WIDGET(it), ic);
1975                   if (elm_widget_item_disabled_get(it))
1976                     elm_widget_disabled_set(ic, EINA_TRUE);
1977                }
1978           }
1979         *source = eina_list_merge(*source, cons);
1980         elm_widget_stringlist_free(cons);
1981      }
1982
1983    return res;
1984 }
1985
1986 static void
1987 _item_realize(Elm_Gen_Item *it,
1988               int               in,
1989               Eina_Bool         calc)
1990 {
1991    const char *treesize;
1992    char buf[1024];
1993    int tsize = 20;
1994    Item_Cache *itc = NULL;
1995
1996    if (it->generation < it->wd->generation) return;
1997    //evas_event_freeze(evas_object_evas_get(it->wd->obj));
1998    if (it->realized)
1999      {
2000         if (it->item->order_num_in != in)
2001           {
2002              it->item->order_num_in = in;
2003              _elm_genlist_item_odd_even_update(it);
2004              _elm_genlist_item_state_update(it, NULL);
2005              _elm_genlist_item_index_update(it);
2006           }
2007         //evas_event_thaw(evas_object_evas_get(it->wd->obj));
2008         //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2009         return;
2010      }
2011    it->item->order_num_in = in;
2012
2013    if (it->item->nocache_once)
2014      it->item->nocache_once = EINA_FALSE;
2015    else if (!it->item->nocache)
2016      itc = _item_cache_find(it);
2017    if (itc && (!it->wd->tree_effect_enabled))
2018      {
2019         VIEW(it) = itc->base_view;
2020         itc->base_view = NULL;
2021         it->spacer = itc->spacer;
2022         itc->spacer = NULL;
2023      }
2024    else
2025      {
2026         const char *stacking_even;
2027         const char *stacking;
2028
2029         VIEW(it) = edje_object_add(evas_object_evas_get(WIDGET(it)));
2030         edje_object_scale_set(VIEW(it),
2031                               elm_widget_scale_get(WIDGET(it)) *
2032                               _elm_config->scale);
2033         evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
2034         elm_widget_sub_object_add(WIDGET(it), VIEW(it));
2035
2036         if (it->item->type & ELM_GENLIST_ITEM_TREE)
2037           snprintf(buf, sizeof(buf), "tree%s/%s", it->wd->mode == ELM_LIST_COMPRESS ? "_compress" : "", it->itc->item_style ?: "default");
2038         else
2039           snprintf(buf, sizeof(buf), "item%s/%s", it->wd->mode == ELM_LIST_COMPRESS ? "_compress" : "", it->itc->item_style ?: "default");
2040
2041         _elm_theme_object_set(WIDGET(it), VIEW(it), "genlist", buf,
2042                               elm_widget_style_get(WIDGET(it)));
2043
2044         stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
2045         if (!stacking_even) stacking_even = "above";
2046         it->item->stacking_even = !!strcmp("above", stacking_even);
2047
2048         stacking = edje_object_data_get(VIEW(it), "stacking");
2049         if (!stacking) stacking = "yes";
2050         it->item->nostacking = !!strcmp("yes", stacking);
2051
2052         edje_object_mirrored_set(VIEW(it),
2053                                  elm_widget_mirrored_get(WIDGET(it)));
2054      }
2055
2056    _elm_genlist_item_odd_even_update(it);
2057
2058    treesize = edje_object_data_get(VIEW(it), "treesize");
2059    if (treesize) tsize = atoi(treesize);
2060    if (!it->spacer && treesize)
2061      {
2062         it->spacer =
2063           evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
2064         evas_object_color_set(it->spacer, 0, 0, 0, 0);
2065         elm_widget_sub_object_add(WIDGET(it), it->spacer);
2066      }
2067    if (it->spacer)
2068      {
2069         evas_object_size_hint_min_set(it->spacer,
2070                                       (it->item->expanded_depth * tsize) * _elm_config->scale, 1);
2071         edje_object_part_swallow(VIEW(it), "elm.swallow.pad", it->spacer);
2072      }
2073    if (!calc)
2074      {
2075         edje_object_signal_callback_add(VIEW(it),
2076                                         "elm,action,expand,toggle",
2077                                         "elm", _signal_expand_toggle, it);
2078         edje_object_signal_callback_add(VIEW(it), "elm,action,expand",
2079                                         "elm", _signal_expand, it);
2080         edje_object_signal_callback_add(VIEW(it), "elm,action,contract",
2081                                         "elm", _signal_contract, it);
2082         _item_mouse_callbacks_add(it, VIEW(it));
2083
2084         if ((it->wd->decorate_mode) && (!it->edit_obj) &&
2085             (it->item->type != ELM_GENLIST_ITEM_GROUP) && (it->itc->decorate_all_item_style))
2086           _decorate_mode_item_realize(it, EINA_FALSE);
2087
2088         _elm_genlist_item_state_update(it, itc);
2089         _elm_genlist_item_index_update(it);
2090      }
2091
2092    if ((calc) && (it->wd->homogeneous) &&
2093        ((it->wd->item_width) ||
2094         ((it->wd->item_width) && (it->wd->group_item_width))))
2095      {
2096         /* homogenous genlist shortcut */
2097         if (!it->item->mincalcd)
2098           {
2099              if (it->group)
2100                {
2101                   it->item->w = it->item->minw = it->wd->group_item_width;
2102                   it->item->h = it->item->minh = it->wd->group_item_height;
2103                }
2104              else
2105                {
2106                   it->item->w = it->item->minw = it->wd->item_width;
2107                   it->item->h = it->item->minh = it->wd->item_height;
2108                }
2109              it->item->mincalcd = EINA_TRUE;
2110           }
2111      }
2112    else
2113      {
2114         /* FIXME: If you see that assert, please notify us and we
2115            will clean our mess */
2116         assert(eina_list_count(it->content_objs) == 0);
2117
2118         _item_text_realize(it, VIEW(it), &it->texts, NULL);
2119         it->content_objs = _item_content_realize(it, VIEW(it), &it->contents, NULL);
2120         _item_state_realize(it, VIEW(it), &it->states, NULL);
2121         if (it->flipped)
2122           {
2123              edje_object_signal_emit(VIEW(it), "elm,state,flip,enabled", "elm");
2124              it->content_objs = _item_flips_realize(it, VIEW(it), &it->contents);
2125           }
2126
2127         if (!it->item->mincalcd)
2128           {
2129              Evas_Coord mw = -1, mh = -1;
2130
2131              if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
2132                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
2133              if (it->wd->mode == ELM_LIST_COMPRESS) mw = it->wd->prev_viewport_w;
2134              edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw,
2135                                                   mh);
2136              if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
2137                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
2138              it->item->w = it->item->minw = mw;
2139              it->item->h = it->item->minh = mh;
2140              it->item->mincalcd = EINA_TRUE;
2141
2142              if ((!it->wd->group_item_width) && (it->group))
2143                {
2144                   it->wd->group_item_width = mw;
2145                   it->wd->group_item_height = mh;
2146                }
2147              else if ((!it->wd->item_width) && (it->item->type == ELM_GENLIST_ITEM_NONE))
2148                {
2149                   it->wd->item_width = mw;
2150                   it->wd->item_height = mh;
2151                }
2152           }
2153         if (!calc) evas_object_show(VIEW(it));
2154      }
2155
2156    if (it->tooltip.content_cb)
2157      {
2158         elm_widget_item_tooltip_content_cb_set(it,
2159                                                it->tooltip.content_cb,
2160                                                it->tooltip.data, NULL);
2161         elm_widget_item_tooltip_style_set(it, it->tooltip.style);
2162         elm_widget_item_tooltip_window_mode_set(it, it->tooltip.free_size);
2163      }
2164
2165    if (it->mouse_cursor)
2166      elm_widget_item_cursor_set(it, it->mouse_cursor);
2167
2168    it->realized = EINA_TRUE;
2169    it->want_unrealize = EINA_FALSE;
2170
2171    if (itc) _item_cache_free(itc);
2172    //evas_event_thaw(evas_object_evas_get(it->wd->obj));
2173    //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2174    if (!calc)
2175      evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
2176
2177    if ((!calc) && (it->wd->decorate_mode) && (it->item->type != ELM_GENLIST_ITEM_GROUP))
2178      {
2179         if (it->itc->decorate_all_item_style)
2180           {
2181              if (!it->edit_obj) _decorate_mode_item_realize(it, EINA_FALSE);
2182              edje_object_message_signal_process(it->edit_obj);
2183           }
2184      }
2185    edje_object_message_signal_process(VIEW(it));
2186 }
2187
2188 static void
2189 _item_unrealize_cb(Elm_Gen_Item *it)
2190 {
2191    if (it->item->nocache_once || it->item->nocache)
2192      {
2193         evas_object_del(VIEW(it));
2194         VIEW(it) = NULL;
2195         if (it->spacer)
2196           {
2197              evas_object_del(it->spacer);
2198              it->spacer = NULL;
2199           }
2200      }
2201    else
2202      {
2203         edje_object_mirrored_set(VIEW(it),
2204                                  elm_widget_mirrored_get(WIDGET(it)));
2205         edje_object_scale_set(VIEW(it),
2206                               elm_widget_scale_get(WIDGET(it))
2207                               * _elm_config->scale);
2208         _item_cache_add(it);
2209      }
2210
2211    _mode_item_unrealize(it);
2212    it->states = NULL;
2213    it->realized = EINA_FALSE;
2214    it->want_unrealize = EINA_FALSE;
2215    if (it->wd->decorate_mode) _decorate_mode_item_unrealize(it);
2216 }
2217
2218 static Eina_Bool
2219 _item_block_recalc(Item_Block *itb,
2220                    int         in,
2221                    Eina_Bool   qadd)
2222 {
2223    const Eina_List *l;
2224    Elm_Gen_Item *it;
2225    Evas_Coord minw = 0, minh = 0;
2226    Eina_Bool showme = EINA_FALSE, changed = EINA_FALSE;
2227    Evas_Coord y = 0;
2228
2229    //evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2230    itb->num = in;
2231    EINA_LIST_FOREACH(itb->items, l, it)
2232      {
2233         if (it->generation < it->wd->generation) continue;
2234         showme |= it->item->showme;
2235         if (!itb->realized)
2236           {
2237              if (qadd)
2238                {
2239                   if (!it->item->mincalcd) changed = EINA_TRUE;
2240                   if (changed)
2241                     {
2242                        _item_realize(it, in, EINA_TRUE);
2243                        _elm_genlist_item_unrealize(it, EINA_TRUE);
2244                     }
2245                }
2246              else
2247                {
2248                   _item_realize(it, in, EINA_TRUE);
2249                   _elm_genlist_item_unrealize(it, EINA_TRUE);
2250                }
2251           }
2252         else
2253           _item_realize(it, in, EINA_FALSE);
2254         minh += it->item->minh;
2255         if (minw < it->item->minw) minw = it->item->minw;
2256         in++;
2257         it->x = 0;
2258         it->y = y;
2259         y += it->item->h;
2260      }
2261    itb->minw = minw;
2262    itb->minh = minh;
2263    itb->changed = EINA_FALSE;
2264    itb->position_update = EINA_FALSE;
2265    //evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2266    //evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2267    return showme;
2268 }
2269
2270 static void
2271 _item_block_realize(Item_Block *itb)
2272 {
2273    if (itb->realized) return;
2274    itb->realized = EINA_TRUE;
2275    itb->want_unrealize = EINA_FALSE;
2276 }
2277
2278 static void
2279 _item_block_unrealize(Item_Block *itb)
2280 {
2281    const Eina_List *l;
2282    Elm_Gen_Item *it;
2283    Eina_Bool dragging = EINA_FALSE;
2284
2285    if (!itb->realized) return;
2286    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2287    EINA_LIST_FOREACH(itb->items, l, it)
2288      {
2289         if (itb->must_recalc || !it->group)
2290           {
2291              if (it->dragging)
2292                {
2293                   dragging = EINA_TRUE;
2294                   it->want_unrealize = EINA_TRUE;
2295                }
2296              else
2297                _elm_genlist_item_unrealize(it, EINA_FALSE);
2298           }
2299      }
2300    if (!dragging)
2301      {
2302         itb->realized = EINA_FALSE;
2303         itb->want_unrealize = EINA_TRUE;
2304      }
2305    else
2306      itb->want_unrealize = EINA_FALSE;
2307    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2308    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2309 }
2310
2311 static int
2312 _get_space_for_reorder_item(Elm_Gen_Item *it)
2313 {
2314    Evas_Coord rox, roy, row, roh, oy, oh;
2315    Eina_Bool top = EINA_FALSE;
2316    Elm_Gen_Item *reorder_it = it->wd->reorder_it;
2317    if (!reorder_it) return 0;
2318
2319    evas_object_geometry_get(it->wd->pan_smart, NULL, &oy, NULL, &oh);
2320    evas_object_geometry_get(it->wd->VIEW(reorder_it), &rox, &roy, &row, &roh);
2321
2322    if ((it->wd->reorder_start_y < it->item->block->y) &&
2323        (roy - oy + (roh / 2) >= it->item->block->y - it->wd->pan_y))
2324      {
2325         it->item->block->reorder_offset = it->wd->reorder_it->item->h * -1;
2326         if (it->item->block->count == 1)
2327           it->wd->reorder_rel = it;
2328      }
2329    else if ((it->wd->reorder_start_y >= it->item->block->y) &&
2330             (roy - oy + (roh / 2) <= it->item->block->y - it->wd->pan_y))
2331      {
2332         it->item->block->reorder_offset = it->wd->reorder_it->item->h;
2333      }
2334    else
2335      it->item->block->reorder_offset = 0;
2336
2337    it->item->scrl_y += it->item->block->reorder_offset;
2338
2339    top = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2340                               rox, roy + (roh / 2), row, 1));
2341    if (top)
2342      {
2343         it->wd->reorder_rel = it;
2344         it->item->scrl_y += it->wd->reorder_it->item->h;
2345         return it->wd->reorder_it->item->h;
2346      }
2347    else
2348      return 0;
2349 }
2350
2351 static Eina_Bool
2352 _reorder_move_animator_cb(void *data)
2353 {
2354    Elm_Gen_Item *it = data;
2355    Eina_Bool down = EINA_FALSE;
2356    double t;
2357    int y, dy = it->item->h / 10 * _elm_config->scale, diff;
2358
2359    t = ((0.0 > (t = ecore_loop_time_get()-it->wd->start_time)) ? 0.0 : t);
2360
2361    if (t <= REORDER_EFFECT_TIME) y = (1 * sin((t / REORDER_EFFECT_TIME) * (M_PI / 2)) * dy);
2362    else y = dy;
2363
2364    diff = abs(it->item->old_scrl_y - it->item->scrl_y);
2365    if (diff > it->item->h) y = diff / 2;
2366
2367    if (it->item->old_scrl_y < it->item->scrl_y)
2368      {
2369         it->item->old_scrl_y += y;
2370         down = EINA_TRUE;
2371      }
2372    else if (it->item->old_scrl_y > it->item->scrl_y)
2373      {
2374         it->item->old_scrl_y -= y;
2375         down = EINA_FALSE;
2376      }
2377
2378    if (it->edit_obj)
2379      _item_position(it, it->edit_obj, it->item->scrl_x, it->item->old_scrl_y);
2380    else
2381      _item_position(it, VIEW(it), it->item->scrl_x, it->item->old_scrl_y);
2382    _group_items_recalc(it->wd);
2383
2384    if ((it->wd->reorder_pan_move) ||
2385        (down && it->item->old_scrl_y >= it->item->scrl_y) ||
2386        (!down && it->item->old_scrl_y <= it->item->scrl_y))
2387      {
2388         it->item->old_scrl_y = it->item->scrl_y;
2389         it->item->move_effect_enabled = EINA_FALSE;
2390         it->wd->reorder_move_animator = NULL;
2391         return ECORE_CALLBACK_CANCEL;
2392      }
2393    return ECORE_CALLBACK_RENEW;
2394 }
2395
2396 static void
2397 _item_position(Elm_Gen_Item *it,
2398                Evas_Object      *view,
2399                Evas_Coord        it_x,
2400                Evas_Coord        it_y)
2401 {
2402    if (!it) return;
2403    if (!view) return;
2404
2405    evas_event_freeze(evas_object_evas_get(it->wd->obj));
2406    evas_object_resize(view, it->item->w, it->item->h);
2407    evas_object_move(view, it_x, it_y);
2408    evas_object_show(view);
2409    evas_event_thaw(evas_object_evas_get(it->wd->obj));
2410    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2411 }
2412
2413 static void
2414 _item_block_position(Item_Block *itb,
2415                      int         in)
2416 {
2417    const Eina_List *l;
2418    Elm_Gen_Item *it;
2419    Elm_Gen_Item *git;
2420    Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2421    Eina_Bool vis = EINA_FALSE;
2422
2423    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2424    evas_object_geometry_get(itb->wd->pan_smart, &ox, &oy, &ow, &oh);
2425    evas_output_viewport_get(evas_object_evas_get(itb->wd->obj), &cvx, &cvy,
2426                             &cvw, &cvh);
2427    EINA_LIST_FOREACH(itb->items, l, it)
2428      {
2429         if (it->generation < it->wd->generation) continue;
2430         else if (it->wd->reorder_it == it) continue;
2431         it->x = 0;
2432         it->y = y;
2433         it->item->w = itb->w;
2434         it->item->scrl_x = itb->x + it->x - it->wd->pan_x + ox;
2435         it->item->scrl_y = itb->y + it->y - it->wd->pan_y + oy;
2436
2437         vis = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2438                                    cvx, cvy, cvw, cvh));
2439         if (!it->group)
2440           {
2441              if ((itb->realized) && (!it->realized))
2442                {
2443                   if (vis) _item_realize(it, in, EINA_FALSE);
2444                }
2445              if (it->realized)
2446                {
2447                   if (vis || it->dragging)
2448                     {
2449                        if (it->wd->reorder_mode)
2450                          y += _get_space_for_reorder_item(it);
2451                        git = it->item->group_item;
2452                        if (git)
2453                          {
2454                             if (git->item->scrl_y < oy)
2455                               git->item->scrl_y = oy;
2456                             if ((git->item->scrl_y + git->item->h) > (it->item->scrl_y + it->item->h))
2457                               git->item->scrl_y = (it->item->scrl_y + it->item->h) - git->item->h;
2458                             git->item->want_realize = EINA_TRUE;
2459                          }
2460                        if ((it->wd->reorder_it) && (it->item->old_scrl_y != it->item->scrl_y))
2461                          {
2462                             if (!it->item->move_effect_enabled)
2463                               {
2464                                  it->item->move_effect_enabled = EINA_TRUE;
2465                                  it->wd->reorder_move_animator =
2466                                     ecore_animator_add(
2467                                        _reorder_move_animator_cb, it);
2468                               }
2469                          }
2470                        if (!it->item->move_effect_enabled)
2471                          {
2472                             if ((it->wd->decorate_mode) && (it->itc->decorate_all_item_style))
2473                               _decorate_mode_item_position(it, it->item->scrl_x,
2474                                                        it->item->scrl_y);
2475                             else
2476                               {
2477                                  if (it->item->mode_view)
2478                                    _item_position(it, it->item->mode_view,
2479                                                   it->item->scrl_x,
2480                                                   it->item->scrl_y);
2481                                  else
2482                                    _item_position(it, VIEW(it), it->item->scrl_x,
2483                                                   it->item->scrl_y);
2484                               }
2485                             it->item->old_scrl_y = it->item->scrl_y;
2486                          }
2487                     }
2488                   else
2489                     {
2490                        if (!it->wd->tree_effect_animator)
2491                          _elm_genlist_item_unrealize(it, EINA_FALSE);
2492                     }
2493                }
2494              in++;
2495           }
2496         else
2497           {
2498              if (vis) it->item->want_realize = EINA_TRUE;
2499           }
2500         y += it->item->h;
2501      }
2502    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2503    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2504 }
2505
2506 static void
2507 _group_items_recalc(void *data)
2508 {
2509    Widget_Data *wd = data;
2510    Eina_List *l;
2511    Elm_Gen_Item *git;
2512
2513    evas_event_freeze(evas_object_evas_get(wd->obj));
2514    EINA_LIST_FOREACH(wd->group_items, l, git)
2515      {
2516         if (git->item->want_realize)
2517           {
2518              if (!git->realized)
2519                _item_realize(git, 0, EINA_FALSE);
2520              evas_object_resize(VIEW(git), wd->minw, git->item->h);
2521              evas_object_move(VIEW(git), git->item->scrl_x, git->item->scrl_y);
2522              evas_object_show(VIEW(git));
2523              evas_object_raise(VIEW(git));
2524           }
2525         else if (!git->item->want_realize && git->realized)
2526           {
2527              if (!git->dragging)
2528                _elm_genlist_item_unrealize(git, EINA_FALSE);
2529           }
2530      }
2531    evas_event_thaw(evas_object_evas_get(wd->obj));
2532    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2533 }
2534
2535 static Eina_Bool
2536 _must_recalc_idler(void *data)
2537 {
2538    Widget_Data *wd = data;
2539    if (wd->calc_job) ecore_job_del(wd->calc_job);
2540    wd->calc_job = ecore_job_add(_calc_job, wd);
2541    wd->must_recalc_idler = NULL;
2542    return ECORE_CALLBACK_CANCEL;
2543 }
2544
2545 static void
2546 _scroll_item(Widget_Data *wd)
2547 {
2548    Elm_Gen_Item *it = NULL;
2549    Evas_Coord gith = 0;
2550    Evas_Coord ow, oh, dx = 0, dy = 0, dw = 0, dh = 0;
2551    if (!wd->show_item) return;
2552
2553    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &oh);
2554    it = wd->show_item;
2555    dx = it->x + it->item->block->x;
2556    dy = it->y + it->item->block->y;
2557    dw = it->item->block->w;
2558    dh = oh;
2559    switch (wd->scrollto_type)
2560      {
2561       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
2562          if (it->item->group_item) gith = it->item->group_item->item->h;
2563          dy -= gith;
2564          break;
2565       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
2566          dy += (it->item->h / 2 - oh / 2);
2567          break;
2568       case ELM_GENLIST_ITEM_SCROLLTO_IN:
2569       default:
2570          if ((wd->expanded_item) &&
2571              ((wd->show_item->y + wd->show_item->item->block->y + wd->show_item->item->h)
2572               - (wd->expanded_item->y + wd->expanded_item->item->block->y) > oh))
2573            {
2574               it = wd->expanded_item;
2575               if (it->item->group_item) gith = it->item->group_item->item->h;
2576               dx = it->x + it->item->block->x;
2577               dy = it->y + it->item->block->y - gith;
2578               dw = it->item->block->w;
2579            }
2580          else
2581            {
2582               if ((it->item->group_item) && (wd->pan_y > (it->y + it->item->block->y)))
2583                 gith = it->item->group_item->item->h;
2584               dy -= gith;
2585               dh = it->item->h;
2586            }
2587          break;
2588      }
2589    if (wd->bring_in)
2590      elm_smart_scroller_region_bring_in(wd->scr, dx, dy, dw, dh);
2591    else
2592      elm_smart_scroller_child_region_show(wd->scr, dx, dy, dw, dh);
2593
2594    it->item->showme = EINA_FALSE;
2595    wd->show_item = NULL;
2596    wd->auto_scroll_enabled = EINA_FALSE;
2597    wd->check_scroll = EINA_FALSE;
2598 }
2599
2600 static void
2601 _calc_job(void *data)
2602 {
2603    Widget_Data *wd = data;
2604    Item_Block *itb, *chb = NULL;
2605    Evas_Coord minw = -1, minh = 0, y = 0, ow, dy = 0, vw;
2606    Evas_Coord pan_w = 0, pan_h = 0;
2607    int in = 0;
2608    Eina_Bool minw_change = EINA_FALSE;
2609    Eina_Bool did_must_recalc = EINA_FALSE;
2610    if (!wd) return;
2611
2612    evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &wd->h);
2613    elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, NULL);
2614
2615    if (wd->w != ow)
2616      wd->w = ow;
2617
2618    evas_event_freeze(evas_object_evas_get(wd->obj));
2619    EINA_INLIST_FOREACH(wd->blocks, itb)
2620      {
2621         Eina_Bool showme = EINA_FALSE;
2622
2623         itb->num = in;
2624         showme = itb->showme;
2625         itb->showme = EINA_FALSE;
2626         if (chb)
2627           {
2628              if (itb->realized) _item_block_unrealize(itb);
2629           }
2630         if ((itb->changed) || ((itb->must_recalc) && (!did_must_recalc)))
2631           {
2632              if (itb->must_recalc)
2633                {
2634                   Eina_List *l;
2635                   Elm_Gen_Item *it;
2636                   EINA_LIST_FOREACH(itb->items, l, it)
2637                     if (it->item->mincalcd) it->item->mincalcd = EINA_FALSE;
2638                   itb->changed = EINA_TRUE;
2639                   if (itb->must_recalc) did_must_recalc = EINA_TRUE;
2640                   if (itb->realized) _item_block_unrealize(itb);
2641                   itb->must_recalc = EINA_FALSE;
2642                }
2643              showme = _item_block_recalc(itb, in, EINA_FALSE);
2644              chb = itb;
2645           }
2646         itb->y = y;
2647         itb->x = 0;
2648         minh += itb->minh;
2649         if (minw == -1) minw = itb->minw;
2650         else if ((!itb->must_recalc) && (minw < itb->minw))
2651           {
2652              minw = itb->minw;
2653              minw_change = EINA_TRUE;
2654           }
2655         if (minw > vw)
2656           {
2657              minw = vw;
2658              minw_change = EINA_TRUE;
2659           }
2660         itb->w = minw;
2661         itb->h = itb->minh;
2662         y += itb->h;
2663         in += itb->count;
2664         if ((showme) && (wd->show_item) && (!wd->show_item->item->queued))
2665           wd->check_scroll = EINA_TRUE;
2666      }
2667    if (minw_change)
2668      {
2669         EINA_INLIST_FOREACH(wd->blocks, itb)
2670           {
2671              itb->minw = minw;
2672              itb->w = itb->minw;
2673           }
2674      }
2675    if ((chb) && (EINA_INLIST_GET(chb)->next))
2676      {
2677         EINA_INLIST_FOREACH(EINA_INLIST_GET(chb)->next, itb)
2678           {
2679              if (itb->realized) _item_block_unrealize(itb);
2680           }
2681      }
2682    wd->realminw = minw;
2683    if (minw < wd->w) minw = wd->w;
2684    if ((minw != wd->minw) || (minh != wd->minh))
2685      {
2686         wd->minw = minw;
2687         wd->minh = minh;
2688         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
2689         _sizing_eval(wd->obj);
2690         if ((wd->anchor_item) && (wd->anchor_item->item->block) && (!wd->auto_scroll_enabled))
2691           {
2692              Elm_Gen_Item *it;
2693              Evas_Coord it_y;
2694
2695              it = wd->anchor_item;
2696              it_y = wd->anchor_y;
2697              elm_smart_scroller_child_pos_set(wd->scr, wd->pan_x,
2698                                               it->item->block->y + it->y + it_y);
2699              wd->anchor_item = it;
2700              wd->anchor_y = it_y;
2701           }
2702      }
2703    if (did_must_recalc)
2704      {
2705         if (!wd->must_recalc_idler)
2706           wd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, wd);
2707      }
2708    if (wd->check_scroll)
2709      {
2710         _pan_child_size_get(wd->pan_smart, &pan_w, &pan_h);
2711         if (EINA_INLIST_GET(wd->show_item) == wd->items->last)
2712           wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
2713        switch (wd->scrollto_type)
2714           {
2715            case ELM_GENLIST_ITEM_SCROLLTO_TOP:
2716               dy = wd->h;
2717               break;
2718            case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
2719               dy = wd->h / 2;
2720               break;
2721            case ELM_GENLIST_ITEM_SCROLLTO_IN:
2722            default:
2723               dy = 0;
2724               break;
2725           }
2726         if (wd->show_item)
2727           {
2728              if ((pan_w > (wd->show_item->x + wd->show_item->item->block->x)) &&
2729                  (pan_h > (wd->show_item->y + wd->show_item->item->block->y + dy)))
2730                {
2731                   _scroll_item(wd);
2732                }
2733           }
2734      }
2735    wd->calc_job = NULL;
2736    evas_object_smart_changed(wd->pan_smart);
2737    evas_event_thaw(evas_object_evas_get(wd->obj));
2738    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2739 }
2740
2741 static void
2742 _update_job(void *data)
2743 {
2744    Widget_Data *wd = data;
2745    Eina_List *l2;
2746    Item_Block *itb;
2747    int num, num0;
2748    Eina_Bool position = EINA_FALSE, recalc = EINA_FALSE;
2749    if (!wd) return;
2750    wd->update_job = NULL;
2751    num = 0;
2752
2753    evas_event_freeze(evas_object_evas_get(wd->obj));
2754    EINA_INLIST_FOREACH(wd->blocks, itb)
2755      {
2756         Evas_Coord itminw, itminh;
2757         Elm_Gen_Item *it;
2758
2759         if (!itb->updateme)
2760           {
2761              num += itb->count;
2762              if (position)
2763                _item_block_position(itb, num);
2764              continue;
2765           }
2766         num0 = num;
2767         recalc = EINA_FALSE;
2768         EINA_LIST_FOREACH(itb->items, l2, it)
2769           {
2770              if (it->item->updateme)
2771                {
2772                   itminw = it->item->minw;
2773                   itminh = it->item->minh;
2774
2775                   it->item->updateme = EINA_FALSE;
2776                   if (it->realized)
2777                     {
2778                        _elm_genlist_item_unrealize(it, EINA_FALSE);
2779                        _item_realize(it, num, EINA_FALSE);
2780                        position = EINA_TRUE;
2781                     }
2782                   else
2783                     {
2784                        _item_realize(it, num, EINA_TRUE);
2785                        _elm_genlist_item_unrealize(it, EINA_TRUE);
2786                     }
2787                   if ((it->item->minw != itminw) || (it->item->minh != itminh))
2788                     recalc = EINA_TRUE;
2789                }
2790              num++;
2791           }
2792         itb->updateme = EINA_FALSE;
2793         if (recalc)
2794           {
2795              position = EINA_TRUE;
2796              itb->changed = EINA_TRUE;
2797              _item_block_recalc(itb, num0, EINA_FALSE);
2798              _item_block_position(itb, num0);
2799           }
2800      }
2801    if (position)
2802      {
2803         if (wd->calc_job) ecore_job_del(wd->calc_job);
2804         wd->calc_job = ecore_job_add(_calc_job, wd);
2805      }
2806    evas_event_thaw(evas_object_evas_get(wd->obj));
2807    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2808 }
2809
2810 static void
2811 _pan_set(Evas_Object *obj,
2812          Evas_Coord   x,
2813          Evas_Coord   y)
2814 {
2815    Pan *sd = evas_object_smart_data_get(obj);
2816    Item_Block *itb;
2817
2818    if (!sd) return;
2819    //   Evas_Coord ow, oh;
2820    //   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2821    //   ow = sd->wd->minw - ow;
2822    //   if (ow < 0) ow = 0;
2823    //   oh = sd->wd->minh - oh;
2824    //   if (oh < 0) oh = 0;
2825    //   if (x < 0) x = 0;
2826    //   if (y < 0) y = 0;
2827    //   if (x > ow) x = ow;
2828    //   if (y > oh) y = oh;
2829    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
2830    sd->wd->pan_x = x;
2831    sd->wd->pan_y = y;
2832
2833    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
2834      {
2835         if ((itb->y + itb->h) > y)
2836           {
2837              Elm_Gen_Item *it;
2838              Eina_List *l2;
2839
2840              EINA_LIST_FOREACH(itb->items, l2, it)
2841                {
2842                   if ((itb->y + it->y) >= y)
2843                     {
2844                        sd->wd->anchor_item = it;
2845                        sd->wd->anchor_y = -(itb->y + it->y - y);
2846                        goto done;
2847                     }
2848                }
2849           }
2850      }
2851 done:
2852    if (!sd->wd->reorder_move_animator) evas_object_smart_changed(obj);
2853 }
2854
2855 static void
2856 _pan_get(Evas_Object *obj,
2857          Evas_Coord  *x,
2858          Evas_Coord  *y)
2859 {
2860    Pan *sd = evas_object_smart_data_get(obj);
2861
2862    if (!sd) return;
2863    if (x) *x = sd->wd->pan_x;
2864    if (y) *y = sd->wd->pan_y;
2865 }
2866
2867 static void
2868 _pan_max_get(Evas_Object *obj,
2869              Evas_Coord  *x,
2870              Evas_Coord  *y)
2871 {
2872    Pan *sd = evas_object_smart_data_get(obj);
2873    Evas_Coord ow, oh;
2874
2875    if (!sd) return;
2876    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2877    ow = sd->wd->minw - ow;
2878    if (ow < 0) ow = 0;
2879    oh = sd->wd->minh - oh;
2880    if (oh < 0) oh = 0;
2881    if (x) *x = ow;
2882    if (y) *y = oh;
2883 }
2884
2885 static void
2886 _pan_min_get(Evas_Object *obj __UNUSED__,
2887              Evas_Coord  *x,
2888              Evas_Coord  *y)
2889 {
2890    if (x) *x = 0;
2891    if (y) *y = 0;
2892 }
2893
2894 static void
2895 _pan_child_size_get(Evas_Object *obj,
2896                     Evas_Coord  *w,
2897                     Evas_Coord  *h)
2898 {
2899    Pan *sd = evas_object_smart_data_get(obj);
2900
2901    if (!sd) return;
2902    if (w) *w = sd->wd->minw;
2903    if (h) *h = sd->wd->minh;
2904 }
2905
2906 static void
2907 _pan_add(Evas_Object *obj)
2908 {
2909    Pan *sd;
2910    Evas_Object_Smart_Clipped_Data *cd;
2911
2912    _pan_sc.add(obj);
2913    cd = evas_object_smart_data_get(obj);
2914    sd = ELM_NEW(Pan);
2915    if (!sd) return;
2916    sd->__clipped_data = *cd;
2917    free(cd);
2918    evas_object_smart_data_set(obj, sd);
2919 }
2920
2921 static void
2922 _pan_del(Evas_Object *obj)
2923 {
2924    Pan *sd = evas_object_smart_data_get(obj);
2925
2926    if (!sd) return;
2927    if (sd->resize_job)
2928      {
2929         ecore_job_del(sd->resize_job);
2930         sd->resize_job = NULL;
2931      }
2932    _pan_sc.del(obj);
2933 }
2934
2935 static void
2936 _pan_resize_job(void *data)
2937 {
2938    Pan *sd = data;
2939    if (!sd) return;
2940    _sizing_eval(sd->wd->obj);
2941    sd->resize_job = NULL;
2942 }
2943
2944 static void
2945 _pan_resize(Evas_Object *obj,
2946             Evas_Coord   w,
2947             Evas_Coord   h)
2948 {
2949    Pan *sd = evas_object_smart_data_get(obj);
2950    Evas_Coord ow, oh;
2951
2952    if (!sd) return;
2953    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2954    if ((ow == w) && (oh == h)) return;
2955    if ((sd->wd->mode == ELM_LIST_COMPRESS) && (ow != w))
2956      {
2957         /* fix me later */
2958         if (sd->resize_job) ecore_job_del(sd->resize_job);
2959         sd->resize_job = ecore_job_add(_pan_resize_job, sd);
2960      }
2961    sd->wd->pan_changed = EINA_TRUE;
2962    evas_object_smart_changed(obj);
2963    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2964    sd->wd->calc_job = NULL;
2965 /* OLD
2966    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2967    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
2968  */
2969 }
2970
2971 static void
2972 _pan_calculate(Evas_Object *obj)
2973 {
2974    Pan *sd = evas_object_smart_data_get(obj);
2975    Item_Block *itb;
2976    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2977    int in = 0;
2978    Elm_Gen_Item *git;
2979    Eina_List *l;
2980
2981    if (!sd) return;
2982    evas_event_freeze(evas_object_evas_get(obj));
2983
2984    if (sd->wd->pan_changed)
2985      {
2986         _calc_job(sd->wd);
2987         sd->wd->pan_changed = EINA_FALSE;
2988      }
2989
2990    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
2991    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
2992    EINA_LIST_FOREACH(sd->wd->group_items, l, git)
2993      {
2994         git->item->want_realize = EINA_FALSE;
2995      }
2996    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
2997      {
2998         itb->w = sd->wd->minw;
2999         if (ELM_RECTS_INTERSECT(itb->x - sd->wd->pan_x + ox,
3000                                 itb->y - sd->wd->pan_y + oy,
3001                                 itb->w, itb->h,
3002                                 cvx, cvy, cvw, cvh))
3003           {
3004              if ((!itb->realized) || (itb->changed))
3005                _item_block_realize(itb);
3006              _item_block_position(itb, in);
3007           }
3008         else
3009           {
3010              if (itb->realized) _item_block_unrealize(itb);
3011           }
3012         in += itb->count;
3013      }
3014    if ((!sd->wd->reorder_it) || (sd->wd->reorder_pan_move))
3015       _group_items_recalc(sd->wd);
3016    if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
3017      {
3018         if (sd->wd->pan_y != sd->wd->reorder_old_pan_y)
3019            sd->wd->reorder_pan_move = EINA_TRUE;
3020         else sd->wd->reorder_pan_move = EINA_FALSE;
3021         evas_object_raise(sd->wd->VIEW(reorder_it));
3022         sd->wd->reorder_old_pan_y = sd->wd->pan_y;
3023         sd->wd->start_time = ecore_loop_time_get();
3024      }
3025
3026    if (sd->wd->tree_effect_enabled && (sd->wd->move_effect_mode != ELM_GENLIST_TREE_EFFECT_NONE))
3027      {
3028         if (!sd->wd->tree_effect_animator)
3029           {
3030              _item_tree_effect_before(sd->wd->expanded_item);
3031              evas_object_raise(sd->wd->alpha_bg);
3032              evas_object_show(sd->wd->alpha_bg);
3033              sd->wd->start_time = ecore_time_get();
3034              sd->wd->tree_effect_animator = ecore_animator_add(_tree_effect_animator_cb, sd->wd);
3035           }
3036      }
3037    else
3038      _item_auto_scroll(sd->wd);
3039
3040    evas_event_thaw(evas_object_evas_get(obj));
3041    evas_event_thaw_eval(evas_object_evas_get(obj));
3042 }
3043
3044 static void
3045 _pan_move(Evas_Object *obj,
3046           Evas_Coord   x __UNUSED__,
3047           Evas_Coord   y __UNUSED__)
3048 {
3049    Pan *sd = evas_object_smart_data_get(obj);
3050
3051    if (!sd) return;
3052
3053    sd->wd->pan_changed = EINA_TRUE;
3054    evas_object_smart_changed(obj);
3055    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3056    sd->wd->calc_job = NULL;
3057 }
3058
3059 static void
3060 _hold_on(void        *data __UNUSED__,
3061          Evas_Object *obj,
3062          void        *event_info __UNUSED__)
3063 {
3064    Widget_Data *wd = elm_widget_data_get(obj);
3065    if (!wd) return;
3066    elm_smart_scroller_hold_set(wd->scr, 1);
3067 }
3068
3069 static void
3070 _hold_off(void        *data __UNUSED__,
3071           Evas_Object *obj,
3072           void        *event_info __UNUSED__)
3073 {
3074    Widget_Data *wd = elm_widget_data_get(obj);
3075    if (!wd) return;
3076    elm_smart_scroller_hold_set(wd->scr, 0);
3077 }
3078
3079 static void
3080 _freeze_on(void        *data __UNUSED__,
3081            Evas_Object *obj,
3082            void        *event_info __UNUSED__)
3083 {
3084    Widget_Data *wd = elm_widget_data_get(obj);
3085    if (!wd) return;
3086    elm_smart_scroller_freeze_set(wd->scr, 1);
3087 }
3088
3089 static void
3090 _freeze_off(void        *data __UNUSED__,
3091             Evas_Object *obj,
3092             void        *event_info __UNUSED__)
3093 {
3094    Widget_Data *wd = elm_widget_data_get(obj);
3095    if (!wd) return;
3096    elm_smart_scroller_freeze_set(wd->scr, 0);
3097 }
3098
3099 static void
3100 _scr_anim_start(void        *data,
3101                 Evas_Object *obj __UNUSED__,
3102                 void        *event_info __UNUSED__)
3103 {
3104    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
3105 }
3106
3107 static void
3108 _scr_anim_stop(void        *data,
3109                Evas_Object *obj __UNUSED__,
3110                void        *event_info __UNUSED__)
3111 {
3112    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
3113 }
3114
3115 static void
3116 _scr_drag_start(void            *data,
3117                 Evas_Object     *obj __UNUSED__,
3118                 void            *event_info __UNUSED__)
3119 {
3120    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
3121 }
3122
3123 static void
3124 _scr_drag_stop(void            *data,
3125                Evas_Object     *obj __UNUSED__,
3126                void            *event_info __UNUSED__)
3127 {
3128    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
3129 }
3130
3131 static void
3132 _edge_left(void        *data,
3133            Evas_Object *scr __UNUSED__,
3134            void        *event_info __UNUSED__)
3135 {
3136    Evas_Object *obj = data;
3137    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
3138 }
3139
3140 static void
3141 _edge_right(void        *data,
3142             Evas_Object *scr __UNUSED__,
3143             void        *event_info __UNUSED__)
3144 {
3145    Evas_Object *obj = data;
3146    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
3147 }
3148
3149 static void
3150 _edge_top(void        *data,
3151           Evas_Object *scr __UNUSED__,
3152           void        *event_info __UNUSED__)
3153 {
3154    Evas_Object *obj = data;
3155    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
3156 }
3157
3158 static void
3159 _edge_bottom(void        *data,
3160              Evas_Object *scr __UNUSED__,
3161              void        *event_info __UNUSED__)
3162 {
3163    Evas_Object *obj = data;
3164    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
3165 }
3166
3167 static void
3168 _mode_item_realize(Elm_Gen_Item *it)
3169 {
3170    char buf[1024];
3171
3172    if ((it->item->mode_view) || (it->generation < it->wd->generation)) return;
3173
3174    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3175    it->item->mode_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
3176    edje_object_scale_set(it->item->mode_view,
3177                          elm_widget_scale_get(WIDGET(it)) *
3178                          _elm_config->scale);
3179    evas_object_smart_member_add(it->item->mode_view, it->wd->pan_smart);
3180    elm_widget_sub_object_add(WIDGET(it), it->item->mode_view);
3181
3182    strncpy(buf, "item", sizeof(buf));
3183    if (it->wd->mode == ELM_LIST_COMPRESS)
3184      strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3185
3186    if (it->item->order_num_in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf));
3187    strncat(buf, "/", sizeof(buf) - strlen(buf));
3188    strncat(buf, it->itc->decorate_item_style, sizeof(buf) - strlen(buf));
3189
3190    _elm_theme_object_set(WIDGET(it), it->item->mode_view, "genlist", buf,
3191                          elm_widget_style_get(WIDGET(it)));
3192    edje_object_mirrored_set(it->item->mode_view,
3193                             elm_widget_mirrored_get(WIDGET(it)));
3194
3195    /* signal callback add */
3196    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_DOWN,
3197                                   _mouse_down, it);
3198    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_UP,
3199                                   _mouse_up, it);
3200    evas_object_event_callback_add(it->item->mode_view, EVAS_CALLBACK_MOUSE_MOVE,
3201                                   _mouse_move, it);
3202
3203    /* text_get, content_get, state_get */
3204    /* FIXME: If you see that assert, please notify us and we
3205       will clean our mess */
3206    assert(eina_list_count(it->item->mode_content_objs) == 0);
3207
3208    _item_text_realize(it, it->item->mode_view, &it->item->mode_texts, NULL);
3209    it->item->mode_content_objs =
3210      _item_content_realize(it, it->item->mode_view,
3211                            &it->item->mode_contents, NULL);
3212    _item_state_realize(it, it->item->mode_view, &it->item->mode_states, NULL);
3213
3214    edje_object_part_swallow(it->item->mode_view,
3215                             edje_object_data_get(it->item->mode_view, "mode_part"),
3216                             VIEW(it));
3217
3218    it->want_unrealize = EINA_FALSE;
3219    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3220    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3221 }
3222
3223 static void
3224 _mode_item_unrealize(Elm_Gen_Item *it)
3225 {
3226    Widget_Data *wd = it->wd;
3227    Evas_Object *content;
3228    if (!it->item->mode_view) return;
3229
3230    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3231    elm_widget_stringlist_free(it->item->mode_texts);
3232    it->item->mode_texts = NULL;
3233    elm_widget_stringlist_free(it->item->mode_contents);
3234    it->item->mode_contents = NULL;
3235    elm_widget_stringlist_free(it->item->mode_states);
3236
3237    EINA_LIST_FREE(it->item->mode_content_objs, content)
3238      evas_object_del(content);
3239
3240    edje_object_part_unswallow(it->item->mode_view, VIEW(it));
3241    evas_object_smart_member_add(VIEW(it), wd->pan_smart);
3242    evas_object_del(it->item->mode_view);
3243    it->item->mode_view = NULL;
3244
3245    if (wd->mode_item == it)
3246      wd->mode_item = NULL;
3247    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3248    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3249 }
3250
3251 static void
3252 _item_mode_set(Elm_Gen_Item *it)
3253 {
3254    if (!it) return;
3255    Widget_Data *wd = it->wd;
3256    if (!wd) return;
3257    char buf[1024];
3258
3259    wd->mode_item = it;
3260    it->item->nocache_once = EINA_TRUE;
3261
3262    if (wd->scr_hold_timer)
3263      {
3264         ecore_timer_del(wd->scr_hold_timer);
3265         wd->scr_hold_timer = NULL;
3266      }
3267    elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
3268    wd->scr_hold_timer = ecore_timer_add(0.1, _scr_hold_timer_cb, wd);
3269
3270    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3271    _mode_item_realize(it);
3272    if (it->item->group_item)
3273      evas_object_raise(it->item->VIEW(group_item));
3274    _item_position(it, it->item->mode_view, it->item->scrl_x, it->item->scrl_y);
3275    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3276    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3277
3278    snprintf(buf, sizeof(buf), "elm,state,%s,active", wd->decorate_type);
3279    edje_object_signal_emit(it->item->mode_view, buf, "elm");
3280 }
3281
3282 static void
3283 _item_mode_unset(Widget_Data *wd)
3284 {
3285    if (!wd) return;
3286    if (!wd->mode_item) return;
3287    char buf[1024], buf2[1024];
3288    Elm_Gen_Item *it;
3289
3290    it = wd->mode_item;
3291    it->item->nocache_once = EINA_TRUE;
3292
3293    snprintf(buf, sizeof(buf), "elm,state,%s,passive", wd->decorate_type);
3294    snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished", wd->decorate_type);
3295
3296    edje_object_signal_emit(it->item->mode_view, buf, "elm");
3297    edje_object_signal_callback_add(it->item->mode_view, buf2, "elm", _mode_finished_signal_cb, it);
3298
3299    wd->mode_item = NULL;
3300 }
3301
3302 static void
3303 _decorate_mode_item_position(Elm_Gen_Item *it, int itx, int ity)
3304 {
3305    if ((!it) || (!it->wd->decorate_mode)) return;
3306    evas_object_resize(it->edit_obj, it->item->w, it->item->h);
3307    evas_object_move(it->edit_obj, itx, ity);
3308 }
3309
3310 static void
3311 _decorate_mode_item_realize(Elm_Gen_Item *it, Eina_Bool effect_on)
3312 {
3313    char buf[1024];
3314    const char *stacking_even;
3315    const char *stacking;
3316
3317    if ((!it) || (it->item->decorate_mode_item_realized) ||
3318        (it->generation < it->wd->generation))
3319      return;
3320
3321    it->edit_obj = edje_object_add(evas_object_evas_get(WIDGET(it)));
3322    edje_object_scale_set(it->edit_obj, elm_widget_scale_get(WIDGET(it)) *
3323                          _elm_config->scale);
3324    evas_object_smart_member_add(it->edit_obj, it->wd->pan_smart);
3325    elm_widget_sub_object_add(WIDGET(it), it->edit_obj);
3326
3327    if (it->item->type & ELM_GENLIST_ITEM_TREE)
3328       strncpy(buf, "tree", sizeof(buf));
3329    else strncpy(buf, "item", sizeof(buf));
3330    if (it->wd->mode == ELM_LIST_COMPRESS)
3331       strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3332
3333    strncat(buf, "/", sizeof(buf) - strlen(buf));
3334    strncat(buf, it->itc->decorate_all_item_style, sizeof(buf) - strlen(buf));
3335
3336    _elm_theme_object_set(WIDGET(it),  it->edit_obj, "genlist", buf,
3337                          elm_widget_style_get(WIDGET(it)));
3338
3339    stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
3340    if (!stacking_even) stacking_even = "above";
3341    it->item->stacking_even = !!strcmp("above", stacking_even);
3342
3343    stacking = edje_object_data_get(VIEW(it), "stacking");
3344    if (!stacking) stacking = "yes";
3345    it->item->nostacking = !!strcmp("yes", stacking);
3346
3347    edje_object_mirrored_set(it->edit_obj,
3348                             elm_widget_mirrored_get(WIDGET(it)));
3349
3350    _elm_genlist_item_odd_even_update(it);
3351    _elm_genlist_item_state_update(it, NULL);
3352
3353    if (effect_on) edje_object_signal_emit(it->edit_obj, "elm,state,edit,enabled,effect", "elm");
3354    else edje_object_signal_emit(it->edit_obj, "elm,state,edit,enabled", "elm");
3355
3356    _item_mouse_callbacks_del(it, VIEW(it));
3357    _item_mouse_callbacks_add(it, it->edit_obj);
3358
3359    _item_text_realize(it, it->edit_obj, &it->item->edit_texts, NULL);
3360    if (it->flipped)  edje_object_signal_emit(it->edit_obj, "elm,state,flip,enabled", "elm");
3361    it->item->edit_content_objs =
3362      _item_content_realize(it, it->edit_obj, &it->item->edit_contents, NULL);
3363    _item_state_realize(it, it->edit_obj, &it->item->edit_states, NULL);
3364    edje_object_part_swallow(it->edit_obj, "elm.swallow.edit.content", VIEW(it));
3365
3366    _decorate_mode_item_position(it, it->item->scrl_x, it->item->scrl_y);
3367    evas_object_show(it->edit_obj);
3368
3369    it->item->decorate_mode_item_realized = EINA_TRUE;
3370    it->want_unrealize = EINA_FALSE;
3371 }
3372
3373 static void
3374 _decorate_mode_item_unrealize(Elm_Gen_Item *it)
3375 {
3376    Evas_Object *icon;
3377    if ((!it) || (!it->item->decorate_mode_item_realized)) return;
3378
3379    edje_object_part_unswallow(it->edit_obj, VIEW(it));
3380    evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
3381    elm_widget_sub_object_add(WIDGET(it), VIEW(it));
3382    _elm_genlist_item_odd_even_update(it);
3383    _elm_genlist_item_state_update(it, NULL);
3384
3385    evas_object_del(it->edit_obj);
3386    it->edit_obj = NULL;
3387    elm_widget_stringlist_free(it->item->edit_texts);
3388    it->item->edit_texts = NULL;
3389    elm_widget_stringlist_free(it->item->edit_contents);
3390    it->item->edit_contents = NULL;
3391    elm_widget_stringlist_free(it->item->edit_states);
3392    it->item->edit_states = NULL;
3393    EINA_LIST_FREE(it->item->edit_content_objs, icon)
3394      evas_object_del(icon);
3395    edje_object_message_signal_process(it->edit_obj);
3396    _item_mouse_callbacks_del(it, it->edit_obj);
3397    _item_mouse_callbacks_add(it, VIEW(it));
3398
3399    it->item->decorate_mode_item_realized = EINA_FALSE;
3400 }
3401
3402 static void
3403 _item_auto_scroll(Widget_Data *wd)
3404 {
3405    if (!wd) return;
3406    Elm_Gen_Item  *tmp_item = NULL;
3407
3408    if ((wd->expanded_item) && (wd->auto_scroll_enabled))
3409      {
3410         tmp_item = eina_list_data_get(eina_list_last(wd->expanded_item->item->items));
3411         if (!tmp_item) return;
3412         wd->show_item = tmp_item;
3413         wd->bring_in = EINA_TRUE;
3414         wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
3415         if ((wd->show_item->item->queued) || (!wd->show_item->item->mincalcd))
3416           {
3417              wd->show_item->item->showme = EINA_TRUE;
3418              wd->auto_scroll_enabled = EINA_FALSE;
3419           }
3420         else
3421           _scroll_item(wd);
3422      }
3423 }
3424
3425 EAPI Evas_Object *
3426 elm_genlist_add(Evas_Object *parent)
3427 {
3428    Evas_Object *obj;
3429    Evas *e;
3430    Widget_Data *wd;
3431    Evas_Coord minw, minh;
3432    static Evas_Smart *smart = NULL;
3433
3434    if (!smart)
3435      {
3436         static Evas_Smart_Class sc;
3437
3438         evas_object_smart_clipped_smart_set(&_pan_sc);
3439         sc = _pan_sc;
3440         sc.name = "elm_genlist_pan";
3441         sc.version = EVAS_SMART_CLASS_VERSION;
3442         sc.add = _pan_add;
3443         sc.del = _pan_del;
3444         sc.resize = _pan_resize;
3445         sc.move = _pan_move;
3446         sc.calculate = _pan_calculate;
3447         if (!(smart = evas_smart_class_new(&sc))) return NULL;
3448      }
3449
3450    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3451
3452    ELM_SET_WIDTYPE(widtype, "genlist");
3453    ELM_GEN_SETUP(wd);
3454    elm_widget_type_set(obj, "genlist");
3455    elm_widget_sub_object_add(parent, obj);
3456    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
3457    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
3458    elm_widget_data_set(obj, wd);
3459    elm_widget_del_hook_set(obj, _del_hook);
3460    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
3461    elm_widget_theme_hook_set(obj, _theme_hook);
3462    elm_widget_can_focus_set(obj, EINA_TRUE);
3463    elm_widget_event_hook_set(obj, _event_hook);
3464    elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
3465    elm_widget_translate_hook_set(obj, _translate_hook);
3466
3467    wd->generation = 1;
3468    wd->scr = elm_smart_scroller_add(e);
3469    elm_smart_scroller_widget_set(wd->scr, obj);
3470    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
3471                                        elm_widget_style_get(obj));
3472    elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
3473                                        _elm_config->thumbscroll_bounce_enable);
3474    elm_widget_resize_object_set(obj, wd->scr);
3475
3476    evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
3477    evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
3478    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
3479    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
3480    evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
3481    evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
3482    evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
3483    evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
3484
3485    wd->obj = obj;
3486    wd->mode = ELM_LIST_SCROLL;
3487    wd->max_items_per_block = MAX_ITEMS_PER_BLOCK;
3488    wd->item_cache_max = wd->max_items_per_block * 2;
3489    wd->longpress_timeout = _elm_config->longpress_timeout;
3490    wd->highlight = EINA_TRUE;
3491
3492    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
3493    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
3494    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
3495    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
3496
3497    wd->pan_smart = evas_object_smart_add(e, smart);
3498    wd->pan = evas_object_smart_data_get(wd->pan_smart);
3499    wd->pan->wd = wd;
3500
3501    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
3502                                      _pan_set, _pan_get, _pan_max_get,
3503                                      _pan_min_get, _pan_child_size_get);
3504
3505    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
3506                              &minw, &minh);
3507    evas_object_size_hint_min_set(obj, minw, minh);
3508
3509    evas_object_smart_callbacks_descriptions_set(obj, _signals);
3510
3511    _mirrored_set(obj, elm_widget_mirrored_get(obj));
3512    _sizing_eval(obj);
3513    return obj;
3514 }
3515
3516 void
3517 _item_select(Elm_Gen_Item *it)
3518 {
3519    if ((it->generation < it->wd->generation) || (it->mode_set) ||
3520        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
3521        (it->wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE))
3522      return;
3523    if (!it->selected)
3524      {
3525         it->selected = EINA_TRUE;
3526         it->wd->selected = eina_list_append(it->wd->selected, it);
3527      }
3528    else if (it->wd->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS) return;
3529
3530    evas_object_ref(WIDGET(it));
3531    it->walking++;
3532    it->wd->walking++;
3533    if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), it);
3534    if (it->generation == it->wd->generation)
3535      evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
3536    it->walking--;
3537    it->wd->walking--;
3538    if ((it->wd->clear_me) && (!it->wd->walking))
3539      _elm_genlist_clear(WIDGET(it), EINA_TRUE);
3540    else
3541      {
3542         if ((!it->walking) && (it->generation < it->wd->generation))
3543           {
3544              if (!it->relcount)
3545                {
3546                   it->del_cb(it);
3547                   elm_widget_item_free(it);
3548                }
3549           }
3550         else
3551           it->wd->last_selected_item = (Elm_Object_Item *)it;
3552      }
3553    evas_object_unref(WIDGET(it));
3554 }
3555
3556 static Evas_Object *
3557 _item_content_get_hook(Elm_Gen_Item *it, const char *part)
3558 {
3559    return edje_object_part_swallow_get(VIEW(it), part);
3560 }
3561
3562 static void
3563 _item_content_set_hook(Elm_Gen_Item *it, const char *part, Evas_Object *content)
3564 {
3565    if (content && part)
3566      {
3567         it->content_objs = eina_list_append(it->content_objs, content);
3568         edje_object_part_swallow(VIEW(it), part, content);
3569      }
3570 }
3571
3572 static Evas_Object *
3573 _item_content_unset_hook(Elm_Gen_Item *it, const char *part)
3574 {
3575    Evas_Object *obj;
3576    obj = edje_object_part_swallow_get(VIEW(it), part);
3577    if (!obj) return NULL;
3578    it->content_objs = eina_list_remove(it->content_objs, obj);
3579    edje_object_part_unswallow(VIEW(it), obj);
3580    return obj;
3581 }
3582
3583 static const char *
3584 _item_text_hook(Elm_Gen_Item *it, const char *part)
3585 {
3586    if (!it->itc->func.text_get) return NULL;
3587    return edje_object_part_text_get(VIEW(it), part);
3588 }
3589
3590 static void
3591 _item_disable_hook(Elm_Object_Item *it)
3592 {
3593    Eina_List *l;
3594    Evas_Object *obj;
3595    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
3596
3597    if (_it->generation < _it->wd->generation) return;
3598
3599    if (_it->selected)
3600      elm_genlist_item_selected_set(it, EINA_FALSE);
3601
3602    if (_it->realized)
3603      {
3604         if (elm_widget_item_disabled_get(it))
3605           {
3606              edje_object_signal_emit(VIEW(_it), "elm,state,disabled", "elm");
3607              if (_it->edit_obj)
3608                edje_object_signal_emit(_it->edit_obj, "elm,state,disabled", "elm");
3609           }
3610         else
3611           {
3612              edje_object_signal_emit(VIEW(_it), "elm,state,enabled", "elm");
3613              if (_it->edit_obj)
3614                edje_object_signal_emit(_it->edit_obj, "elm,state,enabled", "elm");
3615           }
3616         EINA_LIST_FOREACH(_it->content_objs, l, obj)
3617           elm_widget_disabled_set(obj, elm_widget_item_disabled_get(_it));
3618      }
3619 }
3620
3621 static Eina_Bool
3622 _item_del_pre_hook(Elm_Object_Item *it)
3623 {
3624    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
3625
3626    if ((_it->relcount > 0) || (_it->walking > 0))
3627      {
3628         elm_genlist_item_subitems_clear(it);
3629         if (_it->wd->show_item == _it) _it->wd->show_item = NULL;
3630         _elm_genlist_item_del_notserious(_it);
3631         if (_it->item->block)
3632           {
3633              if (_it->realized) _elm_genlist_item_unrealize(_it, EINA_FALSE);
3634              _it->item->block->changed = EINA_TRUE;
3635              if (_it->wd->calc_job) ecore_job_del(_it->wd->calc_job);
3636              _it->wd->calc_job = ecore_job_add(_calc_job, _it->wd);
3637           }
3638         if (_it->parent)
3639           {
3640              _it->parent->item->items =
3641                 eina_list_remove(_it->parent->item->items, it);
3642              _it->parent = NULL;
3643           }
3644         return EINA_FALSE;
3645      }
3646    _item_del(_it);
3647    return EINA_TRUE;
3648 }
3649
3650 static void
3651 _item_signal_emit_hook(Elm_Object_Item *it,
3652                        const char *emission,
3653                        const char *source)
3654 {
3655    edje_object_signal_emit(VIEW(it), emission, source);
3656 }
3657
3658 Elm_Gen_Item *
3659 _elm_genlist_item_new(Widget_Data              *wd,
3660                       const Elm_Gen_Item_Class *itc,
3661                       const void               *data,
3662                       Elm_Gen_Item             *parent,
3663                       Evas_Smart_Cb             func,
3664                       const void               *func_data)
3665 {
3666    Elm_Gen_Item *it;
3667
3668    it = elm_widget_item_new(wd->obj, Elm_Gen_Item);
3669    if (!it) return NULL;
3670    it->wd = wd;
3671    it->generation = wd->generation;
3672    it->itc = itc;
3673    elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)itc);
3674    it->base.data = data;
3675    it->parent = parent;
3676    it->func.func = func;
3677    it->func.data = func_data;
3678    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
3679    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
3680    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
3681    elm_widget_item_text_get_hook_set(it, _item_text_hook);
3682    elm_widget_item_disable_hook_set(it, _item_disable_hook);
3683    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
3684    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
3685
3686    /* TEMPORARY */
3687    it->sel_cb = (Ecore_Cb)_item_select;
3688
3689    return it;
3690 }
3691
3692 static Elm_Gen_Item *
3693 _item_new(Widget_Data                  *wd,
3694           const Elm_Genlist_Item_Class *itc,
3695           const void                   *data,
3696           Elm_Gen_Item                 *parent,
3697           Elm_Genlist_Item_Type         type,
3698           Evas_Smart_Cb                 func,
3699           const void                   *func_data)
3700 {
3701    Elm_Gen_Item *it, *it2;
3702    int depth = 0;
3703
3704    it = _elm_genlist_item_new(wd, itc, data, parent, func, func_data);
3705    if (!it) return NULL;
3706    it->item = ELM_NEW(Elm_Gen_Item_Type);
3707    it->item->type = type;
3708    if (type & ELM_GENLIST_ITEM_GROUP) it->group++;
3709    it->item->expanded_depth = 0;
3710    ELM_GEN_ITEM_SETUP(it);
3711    if (it->parent)
3712      {
3713         if (it->parent->group)
3714           it->item->group_item = parent;
3715         else if (it->parent->item->group_item)
3716           it->item->group_item = it->parent->item->group_item;
3717      }
3718    for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
3719      {
3720         if (!it2->parent->group) depth += 1;
3721      }
3722    it->item->expanded_depth = depth;
3723    wd->item_count++;
3724    return it;
3725 }
3726
3727 static Item_Block *
3728 _item_block_new(Widget_Data *wd, Eina_Bool prepend)
3729 {
3730    Item_Block *itb;
3731
3732    itb = calloc(1, sizeof(Item_Block));
3733    if (!itb) return NULL;
3734    itb->wd = wd;
3735    if (prepend)
3736      {
3737         wd->blocks = eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
3738         _item_block_position_update(wd->blocks, 0);
3739      }
3740    else
3741      {
3742         wd->blocks = eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3743         itb->position_update = EINA_TRUE;
3744         if (wd->blocks != EINA_INLIST_GET(itb))
3745           {
3746              itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
3747           }
3748         else
3749           {
3750              itb->position = 0;
3751           }
3752      }
3753    return itb;
3754 }
3755
3756 static Eina_Bool
3757 _item_block_add(Widget_Data *wd,
3758                 Elm_Gen_Item *it)
3759 {
3760    Item_Block *itb = NULL;
3761
3762    if (!it->item->rel)
3763      {
3764 newblock:
3765         if (it->item->rel)
3766           {
3767              itb = calloc(1, sizeof(Item_Block));
3768              if (!itb) return EINA_FALSE;
3769              itb->wd = wd;
3770              if (!it->item->rel->item->block)
3771                {
3772                   wd->blocks =
3773                     eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3774                   itb->items = eina_list_append(itb->items, it);
3775                   itb->position_update = EINA_TRUE;
3776                   it->position = eina_list_count(itb->items);
3777                   it->position_update = EINA_TRUE;
3778
3779                   if (wd->blocks != EINA_INLIST_GET(itb))
3780                     {
3781                        itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
3782                     }
3783                   else
3784                     {
3785                        itb->position = 0;
3786                     }
3787                }
3788              else
3789                {
3790                   Eina_List *tmp;
3791
3792                   tmp = eina_list_data_find_list(itb->items, it->item->rel);
3793                   if (it->item->before)
3794                     {
3795                        wd->blocks = eina_inlist_prepend_relative
3796                            (wd->blocks, EINA_INLIST_GET(itb),
3797                            EINA_INLIST_GET(it->item->rel->item->block));
3798                        itb->items =
3799                          eina_list_prepend_relative_list(itb->items, it, tmp);
3800
3801                        /* Update index from where we prepended */
3802                        _item_position_update(eina_list_prev(tmp), it->item->rel->position);
3803                        _item_block_position_update(EINA_INLIST_GET(itb),
3804                                                    it->item->rel->item->block->position);
3805                     }
3806                   else
3807                     {
3808                        wd->blocks = eina_inlist_append_relative
3809                            (wd->blocks, EINA_INLIST_GET(itb),
3810                            EINA_INLIST_GET(it->item->rel->item->block));
3811                        itb->items =
3812                          eina_list_append_relative_list(itb->items, it, tmp);
3813
3814                        /* Update block index from where we appended */
3815                        _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
3816                        _item_block_position_update(EINA_INLIST_GET(itb),
3817                                                    it->item->rel->item->block->position + 1);
3818                     }
3819                }
3820           }
3821         else
3822           {
3823              if (it->item->before)
3824                {
3825                   if (wd->blocks)
3826                     {
3827                        itb = (Item_Block *)(wd->blocks);
3828                        if (itb->count >= wd->max_items_per_block)
3829                          {
3830                             itb = _item_block_new(wd, EINA_TRUE);
3831                             if (!itb) return EINA_FALSE;
3832                          }
3833                     }
3834                   else
3835                     {
3836                        itb = _item_block_new(wd, EINA_TRUE);
3837                        if (!itb) return EINA_FALSE;
3838                     }
3839                   itb->items = eina_list_prepend(itb->items, it);
3840
3841                   _item_position_update(itb->items, 0);
3842                }
3843              else
3844                {
3845                   if (wd->blocks)
3846                     {
3847                        itb = (Item_Block *)(wd->blocks->last);
3848                        if (itb->count >= wd->max_items_per_block)
3849                          {
3850                             itb = _item_block_new(wd, EINA_FALSE);
3851                             if (!itb) return EINA_FALSE;
3852                          }
3853                     }
3854                   else
3855                     {
3856                        itb = _item_block_new(wd, EINA_FALSE);
3857                        if (!itb) return EINA_FALSE;
3858                     }
3859                   itb->items = eina_list_append(itb->items, it);
3860                   it->position = eina_list_count(itb->items);
3861                }
3862           }
3863      }
3864    else
3865      {
3866         Eina_List *tmp;
3867
3868         if (it->item->rel->item->queued)
3869           {
3870              /* NOTE: for a strange reason eina_list and eina_inlist don't have the same property
3871                 on sorted insertion order, so the queue is not always ordered like the item list.
3872                 This lead to issue where we depend on an item that is not yet created. As a quick
3873                 work around, we reschedule the calc of the item and stop reordering the list to
3874                 prevent any nasty issue to show up here.
3875               */
3876              wd->queue = eina_list_append(wd->queue, it);
3877              wd->requeued = EINA_TRUE;
3878              it->item->queued = EINA_TRUE;
3879              return EINA_FALSE;
3880           }
3881         itb = it->item->rel->item->block;
3882         if (!itb) goto newblock;
3883         tmp = eina_list_data_find_list(itb->items, it->item->rel);
3884         if (it->item->before)
3885           {
3886              itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
3887              _item_position_update(eina_list_prev(tmp), it->item->rel->position);
3888           }
3889         else
3890           {
3891              itb->items = eina_list_append_relative_list(itb->items, it, tmp);
3892              _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
3893           }
3894      }
3895    itb->count++;
3896    itb->changed = EINA_TRUE;
3897    it->item->block = itb;
3898    if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
3899    itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
3900    if (it->item->rel)
3901      {
3902         it->item->rel->relcount--;
3903         if ((it->item->rel->generation < it->wd->generation) && (!it->item->rel->relcount))
3904           {
3905              _item_del(it->item->rel);
3906              elm_widget_item_free(it->item->rel);
3907           }
3908         it->item->rel = NULL;
3909      }
3910    if (itb->count > itb->wd->max_items_per_block)
3911      {
3912         Item_Block *itb2;
3913         Elm_Gen_Item *it2;
3914         int newc;
3915         Eina_Bool done = EINA_FALSE;
3916
3917         newc = itb->count / 2;
3918
3919         if (EINA_INLIST_GET(itb)->prev)
3920           {
3921              Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
3922
3923              if (itbp->count + newc < wd->max_items_per_block / 2)
3924                {
3925                   /* moving items to previous block */
3926                   while ((itb->count > newc) && (itb->items))
3927                     {
3928                        it2 = eina_list_data_get(itb->items);
3929                        itb->items = eina_list_remove_list(itb->items, itb->items);
3930                        itb->count--;
3931
3932                        itbp->items = eina_list_append(itbp->items, it2);
3933                        it2->item->block = itbp;
3934                        itbp->count++;
3935                     }
3936
3937                   done = EINA_TRUE;
3938                }
3939           }
3940
3941         if (!done && EINA_INLIST_GET(itb)->next)
3942           {
3943              Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
3944
3945              if (itbn->count + newc < wd->max_items_per_block / 2)
3946                {
3947                   /* moving items to next block */
3948                   while ((itb->count > newc) && (itb->items))
3949                     {
3950                        Eina_List *l;
3951
3952                        l = eina_list_last(itb->items);
3953                        it2 = eina_list_data_get(l);
3954                        itb->items = eina_list_remove_list(itb->items, l);
3955                        itb->count--;
3956
3957                        itbn->items = eina_list_prepend(itbn->items, it2);
3958                        it2->item->block = itbn;
3959                        itbn->count++;
3960                     }
3961
3962                   done = EINA_TRUE;
3963                }
3964           }
3965
3966         if (!done)
3967           {
3968              /* moving items to new block */
3969              itb2 = calloc(1, sizeof(Item_Block));
3970              if (!itb2) return EINA_FALSE;
3971              itb2->wd = wd;
3972              wd->blocks =
3973                eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
3974                                            EINA_INLIST_GET(itb));
3975              itb2->changed = EINA_TRUE;
3976              while ((itb->count > newc) && (itb->items))
3977                {
3978                   Eina_List *l;
3979
3980                   l = eina_list_last(itb->items);
3981                   it2 = l->data;
3982                   itb->items = eina_list_remove_list(itb->items, l);
3983                   itb->count--;
3984
3985                   itb2->items = eina_list_prepend(itb2->items, it2);
3986                   it2->item->block = itb2;
3987                   itb2->count++;
3988                }
3989           }
3990      }
3991
3992    return EINA_TRUE;
3993 }
3994
3995 static int
3996 _queue_process(Widget_Data *wd)
3997 {
3998    int n;
3999    Eina_Bool showme = EINA_FALSE;
4000    double t0, t;
4001
4002    t0 = ecore_loop_time_get();
4003    //evas_event_freeze(evas_object_evas_get(wd->obj));
4004    for (n = 0; (wd->queue) && (n < 128); n++)
4005      {
4006         Elm_Gen_Item *it;
4007
4008         it = eina_list_data_get(wd->queue);
4009         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
4010         it->item->queued = EINA_FALSE;
4011         if (!_item_block_add(wd, it)) continue;
4012         if (!wd->blocks)
4013           _item_block_realize(it->item->block);
4014         t = ecore_time_get();
4015         if (it->item->block->changed)
4016           {
4017              showme = _item_block_recalc(it->item->block, it->item->block->num, EINA_TRUE);
4018              it->item->block->changed = 0;
4019              if (wd->pan_changed)
4020                {
4021                   if (wd->calc_job) ecore_job_del(wd->calc_job);
4022                   wd->calc_job = NULL;
4023                   _calc_job(wd);
4024                   wd->pan_changed = EINA_FALSE;
4025                }
4026           }
4027         if (showme) it->item->block->showme = EINA_TRUE;
4028         /* same as eina_inlist_count > 1 */
4029         if (wd->blocks && wd->blocks->next)
4030           {
4031              if ((t - t0) > (ecore_animator_frametime_get())) break;
4032           }
4033      }
4034    //evas_event_thaw(evas_object_evas_get(wd->obj));
4035    //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4036    return n;
4037 }
4038
4039 static Eina_Bool
4040 _idle_process(void *data, Eina_Bool *wakeup)
4041 {
4042    Widget_Data *wd = data;
4043
4044    //xxx
4045    //static double q_start = 0.0;
4046    //if (q_start == 0.0) q_start = ecore_time_get();
4047    //xxx
4048    if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
4049    if (!wd->queue)
4050      {
4051         //xxx
4052         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
4053         //xxx
4054         return ECORE_CALLBACK_CANCEL;
4055      }
4056    return ECORE_CALLBACK_RENEW;
4057 }
4058
4059 static Eina_Bool
4060 _item_idle_enterer(void *data)
4061 {
4062    Widget_Data *wd = data;
4063    Eina_Bool wakeup = EINA_FALSE;
4064    Eina_Bool ok = _idle_process(data, &wakeup);
4065
4066    if (wakeup)
4067      {
4068         // wake up mainloop
4069         if (wd->calc_job) ecore_job_del(wd->calc_job);
4070         wd->calc_job = ecore_job_add(_calc_job, wd);
4071      }
4072    if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
4073    return ok;
4074 }
4075
4076 static void
4077 _item_queue(Widget_Data *wd,
4078             Elm_Gen_Item *it,
4079             Eina_Compare_Cb cb)
4080 {
4081    if (it->item->queued) return;
4082    it->item->queued = EINA_TRUE;
4083    if (cb && !wd->requeued)
4084      wd->queue = eina_list_sorted_insert(wd->queue, cb, it);
4085    else
4086      wd->queue = eina_list_append(wd->queue, it);
4087 // FIXME: why does a freeze then thaw here cause some genlist
4088 // elm_genlist_item_append() to be much much slower?
4089 //   evas_event_freeze(evas_object_evas_get(wd->obj));
4090    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
4091      {
4092         if (wd->queue_idle_enterer)
4093           {
4094              ecore_idle_enterer_del(wd->queue_idle_enterer);
4095              wd->queue_idle_enterer = NULL;
4096           }
4097         _queue_process(wd);
4098      }
4099 //   evas_event_thaw(evas_object_evas_get(wd->obj));
4100 //   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4101    if (!wd->queue_idle_enterer)
4102      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
4103 }
4104
4105 static int
4106 _elm_genlist_item_compare(const void *data, const void *data1)
4107 {
4108    const Elm_Gen_Item *it, *item1;
4109    it = ELM_GEN_ITEM_FROM_INLIST(data);
4110    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
4111    return it->wd->item_compare_cb(it, item1);
4112 }
4113
4114 static int
4115 _elm_genlist_item_list_compare(const void *data, const void *data1)
4116 {
4117    const Elm_Gen_Item *it = data;
4118    const Elm_Gen_Item *item1 = data1;
4119    return it->wd->item_compare_cb(it, item1);
4120 }
4121
4122 static void
4123 _item_move_after(Elm_Gen_Item *it, Elm_Gen_Item *after)
4124 {
4125    if (!it) return;
4126    if (!after) return;
4127
4128    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4129    _item_block_del(it);
4130
4131    it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
4132    it->item->rel = after;
4133    it->item->rel->relcount++;
4134    it->item->before = EINA_FALSE;
4135    if (after->item->group_item) it->item->group_item = after->item->group_item;
4136    _item_queue(it->wd, it, NULL);
4137
4138    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
4139 }
4140
4141 static void
4142 _item_move_before(Elm_Gen_Item *it, Elm_Gen_Item *before)
4143 {
4144    if (!it) return;
4145    if (!before) return;
4146
4147    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4148    _item_block_del(it);
4149    it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
4150    it->item->rel = before;
4151    it->item->rel->relcount++;
4152    it->item->before = EINA_TRUE;
4153    if (before->item->group_item) it->item->group_item = before->item->group_item;
4154    _item_queue(it->wd, it, NULL);
4155
4156    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
4157 }
4158
4159 EAPI unsigned int
4160 elm_genlist_items_count(const Evas_Object *obj)
4161 {
4162    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4163    Widget_Data *wd = elm_widget_data_get(obj);
4164    if (!wd) return 0;
4165    return wd->item_count;
4166 }
4167
4168 EAPI Elm_Object_Item *
4169 elm_genlist_item_append(Evas_Object                  *obj,
4170                         const Elm_Genlist_Item_Class *itc,
4171                         const void                   *data,
4172                         Elm_Object_Item              *parent,
4173                         Elm_Genlist_Item_Type         type,
4174                         Evas_Smart_Cb                 func,
4175                         const void                   *func_data)
4176 {
4177    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4178    Widget_Data *wd = elm_widget_data_get(obj);
4179    if (!wd) return NULL;
4180    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4181                                 func, func_data);
4182    if (!it) return NULL;
4183    if (!it->parent)
4184      {
4185         if (it->group)
4186           wd->group_items = eina_list_append(wd->group_items, it);
4187         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
4188         it->item->rel = NULL;
4189      }
4190    else
4191      {
4192         Elm_Gen_Item *it2 = NULL;
4193         Eina_List *ll = eina_list_last(it->parent->item->items);
4194         if (ll) it2 = ll->data;
4195         it->parent->item->items = eina_list_append(it->parent->item->items, it);
4196         if (!it2) it2 = it->parent;
4197         wd->items =
4198           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4199                                       EINA_INLIST_GET(it2));
4200         it->item->rel = it2;
4201         it->item->rel->relcount++;
4202      }
4203    it->item->before = EINA_FALSE;
4204    _item_queue(wd, it, NULL);
4205    return (Elm_Object_Item *)it;
4206 }
4207
4208 EAPI Elm_Object_Item *
4209 elm_genlist_item_prepend(Evas_Object                  *obj,
4210                          const Elm_Genlist_Item_Class *itc,
4211                          const void                   *data,
4212                          Elm_Object_Item              *parent,
4213                          Elm_Genlist_Item_Type         type,
4214                          Evas_Smart_Cb                 func,
4215                          const void                   *func_data)
4216 {
4217    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4218    Widget_Data *wd = elm_widget_data_get(obj);
4219    if (!wd) return NULL;
4220    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4221                                 func, func_data);
4222    if (!it) return NULL;
4223    if (!it->parent)
4224      {
4225         if (it->group)
4226           wd->group_items = eina_list_prepend(wd->group_items, it);
4227         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
4228         it->item->rel = NULL;
4229      }
4230    else
4231      {
4232         Elm_Gen_Item *it2 = NULL;
4233         Eina_List *ll = it->parent->item->items;
4234         if (ll) it2 = ll->data;
4235         it->parent->item->items = eina_list_prepend(it->parent->item->items, it);
4236         if (!it2) it2 = it->parent;
4237         wd->items =
4238           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4239                                        EINA_INLIST_GET(it2));
4240         it->item->rel = it2;
4241         it->item->rel->relcount++;
4242      }
4243    it->item->before = EINA_TRUE;
4244    _item_queue(wd, it, NULL);
4245    return (Elm_Object_Item *)it;
4246 }
4247
4248 EAPI Elm_Object_Item *
4249 elm_genlist_item_insert_after(Evas_Object                  *obj,
4250                               const Elm_Genlist_Item_Class *itc,
4251                               const void                   *data,
4252                               Elm_Object_Item              *parent,
4253                               Elm_Object_Item              *after,
4254                               Elm_Genlist_Item_Type         type,
4255                               Evas_Smart_Cb                 func,
4256                               const void                   *func_data)
4257 {
4258    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4259    ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
4260    Widget_Data *wd = elm_widget_data_get(obj);
4261    Elm_Gen_Item *_after = (Elm_Gen_Item *) after;
4262    if (!wd) return NULL;
4263    /* It makes no sense to insert after in an empty list with after != NULL, something really bad is happening in your app. */
4264    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4265
4266    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4267                                 func, func_data);
4268    if (!it) return NULL;
4269    if (!it->parent)
4270      {
4271         if ((it->group) && (_after->group))
4272           wd->group_items = eina_list_append_relative(wd->group_items, it,
4273                                                       _after);
4274      }
4275    else
4276      {
4277         it->parent->item->items =
4278            eina_list_append_relative(it->parent->item->items, it, _after);
4279      }
4280    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4281                                            EINA_INLIST_GET(_after));
4282    it->item->rel = _after;
4283    it->item->rel->relcount++;
4284    it->item->before = EINA_FALSE;
4285    _item_queue(wd, it, NULL);
4286    return (Elm_Object_Item *)it;
4287 }
4288
4289 EAPI Elm_Object_Item *
4290 elm_genlist_item_insert_before(Evas_Object                  *obj,
4291                                const Elm_Genlist_Item_Class *itc,
4292                                const void                   *data,
4293                                Elm_Object_Item              *parent,
4294                                Elm_Object_Item              *before,
4295                                Elm_Genlist_Item_Type         type,
4296                                Evas_Smart_Cb                 func,
4297                                const void                   *func_data)
4298 {
4299    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4300    ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
4301    Widget_Data *wd = elm_widget_data_get(obj);
4302    Elm_Gen_Item *_before = (Elm_Gen_Item *) before;
4303    if (!wd) return NULL;
4304    /* It makes no sense to insert before in an empty list with before != NULL, something really bad is happening in your app. */
4305    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4306
4307    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4308                                 func, func_data);
4309    if (!it) return NULL;
4310    if (!it->parent)
4311      {
4312         if (it->group && _before->group)
4313           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
4314                                                        _before);
4315      }
4316    else
4317      {
4318         it->parent->item->items =
4319            eina_list_prepend_relative(it->parent->item->items, it, _before);
4320      }
4321    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4322                                             EINA_INLIST_GET(_before));
4323    it->item->rel = _before;
4324    it->item->rel->relcount++;
4325    it->item->before = EINA_TRUE;
4326    _item_queue(wd, it, NULL);
4327    return (Elm_Object_Item *)it;
4328 }
4329
4330 EAPI Elm_Object_Item *
4331 elm_genlist_item_sorted_insert(Evas_Object                  *obj,
4332                                const Elm_Genlist_Item_Class *itc,
4333                                const void                   *data,
4334                                Elm_Object_Item              *parent,
4335                                Elm_Genlist_Item_Type         type,
4336                                Eina_Compare_Cb               comp,
4337                                Evas_Smart_Cb                 func,
4338                                const void                   *func_data)
4339 {
4340    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4341    Widget_Data *wd = elm_widget_data_get(obj);
4342    if (!wd) return NULL;
4343    Elm_Gen_Item *rel = NULL;
4344    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4345                                 func, func_data);
4346    if (!it) return NULL;
4347
4348    wd->item_compare_cb = comp;
4349
4350    if (it->parent)
4351      {
4352         Eina_List *l;
4353         int cmp_result;
4354
4355         l = eina_list_search_sorted_near_list(it->parent->item->items,
4356                                               _elm_genlist_item_list_compare,
4357                                               it,
4358                                               &cmp_result);
4359         if (l)
4360           rel = eina_list_data_get(l);
4361         else
4362           rel = it->parent;
4363
4364         if (cmp_result >= 0)
4365           {
4366              it->parent->item->items = eina_list_prepend_relative_list(it->parent->item->items, it, l);
4367              wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4368              it->item->before = EINA_FALSE;
4369           }
4370         else if (cmp_result < 0)
4371           {
4372              it->parent->item->items = eina_list_append_relative_list(it->parent->item->items, it, l);
4373              wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4374              it->item->before = EINA_TRUE;
4375           }
4376      }
4377    else
4378      {
4379         if (!wd->state)
4380           {
4381              wd->state = eina_inlist_sorted_state_new();
4382              eina_inlist_sorted_state_init(wd->state, wd->items);
4383              wd->requeued = EINA_FALSE;
4384           }
4385
4386         if (it->group)
4387           wd->group_items = eina_list_append(wd->group_items, it);
4388
4389         wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
4390                                                     _elm_genlist_item_compare, wd->state);
4391
4392         if (EINA_INLIST_GET(it)->next)
4393           {
4394              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4395              it->item->before = EINA_TRUE;
4396           }
4397         else if (EINA_INLIST_GET(it)->prev)
4398           {
4399              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4400              it->item->before = EINA_FALSE;
4401           }
4402      }
4403
4404    if (rel)
4405      {
4406         it->item->rel = rel;
4407         it->item->rel->relcount++;
4408      }
4409
4410    _item_queue(wd, it, _elm_genlist_item_list_compare);
4411
4412    return (Elm_Object_Item *)it;
4413 }
4414
4415 static void
4416 _elm_genlist_clear(Evas_Object *obj, Eina_Bool standby)
4417 {
4418    Eina_Inlist *next, *l;
4419    Widget_Data *wd = elm_widget_data_get(obj);
4420    if (!wd) return;
4421
4422    if (!standby) wd->generation++;
4423
4424    if (wd->state)
4425      {
4426         eina_inlist_sorted_state_free(wd->state);
4427         wd->state = NULL;
4428      }
4429
4430    if (wd->walking > 0)
4431      {
4432         wd->clear_me = EINA_TRUE;
4433         return;
4434      }
4435    evas_event_freeze(evas_object_evas_get(wd->obj));
4436    for (l = wd->items, next = l ? l->next : NULL;
4437         l;
4438         l = next, next = next ? next->next : NULL)
4439      {
4440         Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l);
4441
4442         if (it->generation < wd->generation)
4443           {
4444              Elm_Gen_Item *itn = NULL;
4445
4446              if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
4447              if (itn) itn->walking++; /* prevent early death of subitem */
4448              it->del_cb(it);
4449              elm_widget_item_free(it);
4450              if (itn) itn->walking--;
4451           }
4452      }
4453    wd->clear_me = EINA_FALSE;
4454    wd->pan_changed = EINA_TRUE;
4455    if (wd->calc_job)
4456      {
4457         ecore_job_del(wd->calc_job);
4458         wd->calc_job = NULL;
4459      }
4460    if (wd->selected) wd->selected = eina_list_free(wd->selected);
4461    if (wd->clear_cb) wd->clear_cb(wd);
4462    wd->pan_x = 0;
4463    wd->pan_y = 0;
4464    wd->minw = 0;
4465    wd->minh = 0;
4466
4467    if (wd->alpha_bg) evas_object_del(wd->alpha_bg);
4468    wd->alpha_bg = NULL;
4469
4470    if (wd->pan_smart)
4471      {
4472         evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
4473         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
4474      }
4475    if (wd->sizing_cb) wd->sizing_cb(wd->obj);
4476    elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
4477    evas_event_thaw(evas_object_evas_get(wd->obj));
4478    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4479 }
4480
4481 EAPI void
4482 elm_genlist_clear(Evas_Object *obj)
4483 {
4484    ELM_CHECK_WIDTYPE(obj, widtype);
4485    _elm_genlist_clear(obj, EINA_FALSE);
4486 }
4487
4488 EAPI void
4489 elm_genlist_multi_select_set(Evas_Object *obj,
4490                              Eina_Bool    multi)
4491 {
4492    ELM_CHECK_WIDTYPE(obj, widtype);
4493    Widget_Data *wd = elm_widget_data_get(obj);
4494    if (!wd) return;
4495    wd->multi = !!multi;
4496 }
4497
4498 EAPI Eina_Bool
4499 elm_genlist_multi_select_get(const Evas_Object *obj)
4500 {
4501    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4502    Widget_Data *wd = elm_widget_data_get(obj);
4503    if (!wd) return EINA_FALSE;
4504    return wd->multi;
4505 }
4506
4507 EAPI Elm_Object_Item *
4508 elm_genlist_selected_item_get(const Evas_Object *obj)
4509 {
4510    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4511    Widget_Data *wd = elm_widget_data_get(obj);
4512    if (!wd) return NULL;
4513    if (wd->selected) return wd->selected->data;
4514    return NULL;
4515 }
4516
4517 EAPI const Eina_List *
4518 elm_genlist_selected_items_get(const Evas_Object *obj)
4519 {
4520    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4521    Widget_Data *wd = elm_widget_data_get(obj);
4522    if (!wd) return NULL;
4523    return wd->selected;
4524 }
4525
4526 EAPI Eina_List *
4527 elm_genlist_realized_items_get(const Evas_Object *obj)
4528 {
4529    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4530    Widget_Data *wd = elm_widget_data_get(obj);
4531    Eina_List *list = NULL;
4532    Item_Block *itb;
4533    Eina_Bool done = EINA_FALSE;
4534    if (!wd) return NULL;
4535    EINA_INLIST_FOREACH(wd->blocks, itb)
4536      {
4537         if (itb->realized)
4538           {
4539              Eina_List *l;
4540              Elm_Gen_Item *it;
4541
4542              done = EINA_TRUE;
4543              EINA_LIST_FOREACH(itb->items, l, it)
4544                {
4545                   if (it->realized) list = eina_list_append(list, it);
4546                }
4547           }
4548         else
4549           {
4550              if (done) break;
4551           }
4552      }
4553    return list;
4554 }
4555
4556 EAPI Elm_Object_Item *
4557 elm_genlist_at_xy_item_get(const Evas_Object *obj,
4558                            Evas_Coord         x,
4559                            Evas_Coord         y,
4560                            int               *posret)
4561 {
4562    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4563    Widget_Data *wd = elm_widget_data_get(obj);
4564    Evas_Coord ox, oy, ow, oh;
4565    Item_Block *itb;
4566    Evas_Coord lasty;
4567    if (!wd) return NULL;
4568    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
4569    lasty = oy;
4570    EINA_INLIST_FOREACH(wd->blocks, itb)
4571      {
4572         Eina_List *l;
4573         Elm_Gen_Item *it;
4574
4575         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
4576                                  oy + itb->y - itb->wd->pan_y,
4577                                  itb->w, itb->h, x, y, 1, 1))
4578           continue;
4579         EINA_LIST_FOREACH(itb->items, l, it)
4580           {
4581              Evas_Coord itx, ity;
4582
4583              itx = ox + itb->x + it->x - itb->wd->pan_x;
4584              ity = oy + itb->y + it->y - itb->wd->pan_y;
4585              if (ELM_RECTS_INTERSECT(itx, ity, it->item->w, it->item->h, x, y, 1, 1))
4586                {
4587                   if (posret)
4588                     {
4589                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
4590                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
4591                          *posret = 1;
4592                        else *posret = 0;
4593                     }
4594                   return (Elm_Object_Item *)it;
4595                }
4596              lasty = ity + it->item->h;
4597           }
4598      }
4599    if (posret)
4600      {
4601         if (y > lasty) *posret = 1;
4602         else *posret = -1;
4603      }
4604    return NULL;
4605 }
4606
4607 EAPI Elm_Object_Item *
4608 elm_genlist_first_item_get(const Evas_Object *obj)
4609 {
4610    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4611    Widget_Data *wd = elm_widget_data_get(obj);
4612    if (!wd) return NULL;
4613    if (!wd->items) return NULL;
4614    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
4615    while ((it) && (it->generation < wd->generation))
4616      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4617    return (Elm_Object_Item *)it;
4618 }
4619
4620 EAPI Elm_Object_Item *
4621 elm_genlist_last_item_get(const Evas_Object *obj)
4622 {
4623    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4624    Widget_Data *wd = elm_widget_data_get(obj);
4625    if (!wd) return NULL;
4626    if (!wd->items) return NULL;
4627    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
4628    while ((it) && (it->generation < wd->generation))
4629      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4630    return (Elm_Object_Item *)it;
4631 }
4632
4633 EAPI Elm_Object_Item *
4634 elm_genlist_item_next_get(const Elm_Object_Item *it)
4635 {
4636    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4637    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4638    while (_it)
4639      {
4640         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->next);
4641         if ((_it) && (_it->generation == _it->wd->generation)) break;
4642      }
4643    return (Elm_Object_Item *) _it;
4644 }
4645
4646 EAPI Elm_Object_Item *
4647 elm_genlist_item_prev_get(const Elm_Object_Item *it)
4648 {
4649    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4650    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4651    while (_it)
4652      {
4653         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->prev);
4654         if ((_it) && (_it->generation == _it->wd->generation)) break;
4655      }
4656    return (Elm_Object_Item *) _it;
4657 }
4658
4659 EAPI Elm_Object_Item *
4660 elm_genlist_item_parent_get(const Elm_Object_Item *it)
4661 {
4662    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4663    return (Elm_Object_Item *) ((Elm_Gen_Item *)it)->parent;
4664 }
4665
4666 EAPI void
4667 elm_genlist_item_subitems_clear(Elm_Object_Item *it)
4668 {
4669    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4670    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
4671    if (!wd) return;
4672    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4673
4674    if (!wd->tree_effect_enabled || !wd->move_effect_mode)
4675      _item_subitems_clear(_it);
4676    else
4677      {
4678         if (!wd->tree_effect_animator)
4679           {
4680              wd->expanded_item = _it;
4681              _item_tree_effect_before(_it);
4682              evas_object_raise(wd->alpha_bg);
4683              evas_object_show(wd->alpha_bg);
4684              wd->start_time = ecore_time_get();
4685              wd->tree_effect_animator = ecore_animator_add(_tree_effect_animator_cb, wd);
4686           }
4687         else
4688            _item_subitems_clear(_it);
4689      }
4690 }
4691
4692 EAPI void
4693 elm_genlist_item_selected_set(Elm_Object_Item *it,
4694                               Eina_Bool selected)
4695 {
4696    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4697    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4698    Widget_Data *wd = _it->wd;
4699    if (!wd) return;
4700    if ((_it->generation < wd->generation) || elm_widget_item_disabled_get(_it))
4701      return;
4702    selected = !!selected;
4703    if (_it->selected == selected) return;
4704
4705    if (selected)
4706      {
4707         if (!wd->multi)
4708           {
4709              while (wd->selected)
4710                {
4711                   if (_it->unhighlight_cb) _it->unhighlight_cb(wd->selected->data);
4712                   _it->unsel_cb(wd->selected->data);
4713                }
4714           }
4715         _it->highlight_cb(_it);
4716         _item_select(_it);
4717         return;
4718      }
4719    if (_it->unhighlight_cb) _it->unhighlight_cb(_it);
4720    _it->unsel_cb(_it);
4721 }
4722
4723 EAPI Eina_Bool
4724 elm_genlist_item_selected_get(const Elm_Object_Item *it)
4725 {
4726    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4727    return ((Elm_Gen_Item *)it)->selected;
4728 }
4729
4730 Elm_Gen_Item *
4731 _elm_genlist_expanded_next_item_get(Elm_Gen_Item *it)
4732 {
4733    Elm_Gen_Item *it2;
4734    if (it->item->expanded)
4735      {
4736         it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
4737      }
4738    else
4739      {
4740         it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
4741         while (it2)
4742           {
4743              if (it->item->expanded_depth >= it2->item->expanded_depth) break;
4744              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
4745           }
4746      }
4747    return it2;
4748 }
4749
4750 static void
4751 _elm_genlist_move_items_set(Elm_Gen_Item *it)
4752 {
4753    Eina_List *l;
4754    Elm_Gen_Item *it2 = NULL;
4755    Evas_Coord ox, oy, ow, oh, dh = 0;
4756
4757    it->wd->expanded_next_item = _elm_genlist_expanded_next_item_get(it);
4758
4759    if (it->item->expanded)
4760      {
4761         it->wd->move_items = elm_genlist_realized_items_get(it->wd->obj);
4762         EINA_LIST_FOREACH(it->wd->move_items, l, it2)
4763           {
4764              if (it2 == it->wd->expanded_next_item) break;
4765              it->wd->move_items = eina_list_remove(it->wd->move_items, it2);
4766           }
4767      }
4768    else
4769      {
4770         evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
4771         it2 = it->wd->expanded_next_item;
4772         while (it2 && (dh < oy + oh))
4773           {
4774              dh += it2->item->h;
4775              it->wd->move_items = eina_list_append(it->wd->move_items, it2);
4776              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
4777           }
4778      }
4779 }
4780
4781 EAPI void
4782 elm_genlist_item_expanded_set(Elm_Object_Item  *it,
4783                               Eina_Bool         expanded)
4784 {
4785    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4786    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4787    expanded = !!expanded;
4788    if (_it->item->expanded == expanded) return;
4789    _it->item->expanded = expanded;
4790    _it->wd->expanded_item = _it;
4791    _elm_genlist_move_items_set(_it);
4792
4793    if (_it->wd->tree_effect_enabled && !_it->wd->alpha_bg)
4794       _it->wd->alpha_bg = _create_tray_alpha_bg(WIDGET(_it));
4795
4796    if (_it->item->expanded)
4797      {
4798         _it->wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_EXPAND;
4799         if (_it->realized)
4800           edje_object_signal_emit(VIEW(_it), "elm,state,expanded", "elm");
4801         evas_object_smart_callback_call(WIDGET(_it), SIG_EXPANDED, _it);
4802         _it->wd->auto_scroll_enabled = EINA_TRUE;
4803      }
4804    else
4805      {
4806         _it->wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_CONTRACT;
4807         if (_it->realized)
4808           edje_object_signal_emit(VIEW(_it), "elm,state,contracted", "elm");
4809         evas_object_smart_callback_call(WIDGET(_it), SIG_CONTRACTED, _it);
4810         _it->wd->auto_scroll_enabled = EINA_FALSE;
4811      }
4812 }
4813
4814 EAPI Eina_Bool
4815 elm_genlist_item_expanded_get(const Elm_Object_Item *it)
4816 {
4817    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4818    return ((Elm_Gen_Item *)it)->item->expanded;
4819 }
4820
4821 EAPI int
4822 elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it)
4823 {
4824    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
4825    return ((Elm_Gen_Item *)it)->item->expanded_depth;
4826 }
4827
4828 static Eina_Bool
4829 _elm_genlist_item_compute_coordinates(Elm_Object_Item *it,
4830                                       Elm_Genlist_Item_Scrollto_Type type,
4831                                       Evas_Coord *x,
4832                                       Evas_Coord *y,
4833                                       Evas_Coord *w,
4834                                       Evas_Coord *h)
4835 {
4836    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4837    Evas_Coord gith = 0;
4838    if (_it->generation < _it->wd->generation) return EINA_FALSE;
4839    if ((_it->item->queued) || (!_it->item->mincalcd))
4840      {
4841         _it->wd->show_item = _it;
4842         _it->wd->bring_in = EINA_FALSE;
4843         _it->wd->scrollto_type = type;
4844         _it->item->showme = EINA_TRUE;
4845         return EINA_FALSE;
4846      }
4847    if (_it->wd->show_item)
4848      {
4849         _it->wd->show_item->item->showme = EINA_FALSE;
4850         _it->wd->show_item = NULL;
4851      }
4852
4853    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, w, h);
4854    switch(type)
4855      {
4856       case ELM_GENLIST_ITEM_SCROLLTO_IN:
4857          if ((_it->item->group_item) &&
4858             (_it->wd->pan_y > (_it->y + _it->item->block->y)))
4859              gith = _it->item->group_item->item->h;
4860
4861          *h = _it->item->h;
4862          *y = _it->y + _it->item->block->y - gith;
4863          break;
4864       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
4865          if (_it->item->group_item) gith = _it->item->group_item->item->h;
4866          *y = _it->y + _it->item->block->y - gith;
4867          break;
4868       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
4869          *y = _it->y + _it->item->block->y - *h / 2 + _it->item->h / 2;
4870          break;
4871       default:
4872          return EINA_FALSE;
4873      }
4874
4875    *x = _it->x + _it->item->block->x;
4876    *w = _it->item->block->w;
4877    return EINA_TRUE;
4878 }
4879
4880 EAPI void
4881 elm_genlist_item_promote(Elm_Object_Item *it)
4882 {
4883    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4884    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4885    if (_it->generation < _it->wd->generation) return;
4886    _item_move_before(_it,
4887                      (Elm_Gen_Item *) elm_genlist_first_item_get(WIDGET(_it)));
4888 }
4889
4890 EAPI void
4891 elm_genlist_item_demote(Elm_Object_Item *it)
4892 {
4893    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4894    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4895    if (_it->generation < _it->wd->generation) return;
4896    _item_move_after(_it,
4897                     (Elm_Gen_Item *) elm_genlist_last_item_get(WIDGET(_it)));
4898 }
4899
4900 EAPI void
4901 elm_genlist_item_show(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
4902 {
4903    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4904    Evas_Coord x, y, w, h;
4905    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4906
4907    if (_elm_genlist_item_compute_coordinates(it, type, &x, &y, &w, &h))
4908      elm_smart_scroller_child_region_show(_it->wd->scr, x, y, w, h);
4909 }
4910
4911 EAPI void
4912 elm_genlist_item_bring_in(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
4913 {
4914
4915    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4916    Evas_Coord x, y, w, h;
4917    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4918
4919    if (_elm_genlist_item_compute_coordinates(it, type, &x, &y, &w, &h))
4920      elm_smart_scroller_region_bring_in(_it->wd->scr,x, y, w, h);
4921 }
4922
4923 EAPI void
4924 elm_genlist_item_all_contents_unset(Elm_Object_Item *it, Eina_List **l)
4925 {
4926    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4927
4928    Evas_Object *content;
4929    EINA_LIST_FREE(((Elm_Gen_Item *)it)->content_objs, content)
4930      {
4931         elm_widget_sub_object_del(WIDGET(it), content);
4932         evas_object_smart_member_del(content);
4933         evas_object_hide(content);
4934         if (l)
4935           *l = eina_list_append(*l, content);
4936      }
4937 }
4938
4939 EAPI void
4940 elm_genlist_item_update(Elm_Object_Item *it)
4941 {
4942    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4943    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4944
4945    if (!_it->item->block) return;
4946    if (_it->generation < _it->wd->generation) return;
4947    _it->item->mincalcd = EINA_FALSE;
4948    _it->item->updateme = EINA_TRUE;
4949    _it->item->block->updateme = EINA_TRUE;
4950    if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
4951    _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
4952 }
4953
4954 EAPI void
4955 elm_genlist_item_fields_update(Elm_Object_Item *it,
4956                                const char *parts,
4957                                Elm_Genlist_Item_Field_Type itf)
4958 {
4959    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4960    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4961
4962    if (!_it->item->block) return;
4963    if (_it->generation < _it->wd->generation) return;
4964
4965    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT))
4966      _item_text_realize(_it, VIEW(_it), &_it->texts, parts);
4967    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
4968      {
4969         _it->content_objs = _item_content_unrealize(_it, VIEW(_it),
4970                                                    &_it->contents, parts);
4971         _it->content_objs = _item_content_realize(_it, VIEW(_it),
4972                                                  &_it->contents, parts);
4973      }
4974    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
4975      _item_state_realize(_it, VIEW(_it), &_it->states, parts);
4976 }
4977
4978 EAPI void
4979 elm_genlist_item_item_class_update(Elm_Object_Item *it,
4980                                    const Elm_Genlist_Item_Class *itc)
4981 {
4982    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4983    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4984
4985    if (!_it->item->block) return;
4986    EINA_SAFETY_ON_NULL_RETURN(itc);
4987    if (_it->generation < _it->wd->generation) return;
4988    _it->itc = itc;
4989    _it->item->nocache_once = EINA_TRUE;
4990    elm_genlist_item_update(it);
4991 }
4992
4993 EAPI const Elm_Genlist_Item_Class *
4994 elm_genlist_item_item_class_get(const Elm_Object_Item *it)
4995 {
4996    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4997    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4998    if (_it->generation < _it->wd->generation) return NULL;
4999    return _it->itc;
5000 }
5001
5002 static Evas_Object *
5003 _elm_genlist_item_label_create(void        *data,
5004                                Evas_Object *obj __UNUSED__,
5005                                Evas_Object *tooltip,
5006                                void        *it __UNUSED__)
5007 {
5008    Evas_Object *label = elm_label_add(tooltip);
5009    if (!label)
5010      return NULL;
5011    elm_object_style_set(label, "tooltip");
5012    elm_object_text_set(label, data);
5013    return label;
5014 }
5015
5016 static void
5017 _elm_genlist_item_label_del_cb(void        *data,
5018                                Evas_Object *obj __UNUSED__,
5019                                void        *event_info __UNUSED__)
5020 {
5021    eina_stringshare_del(data);
5022 }
5023
5024 EAPI void
5025 elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
5026                                   const char      *text)
5027 {
5028    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5029    text = eina_stringshare_add(text);
5030    elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
5031                                            text,
5032                                            _elm_genlist_item_label_del_cb);
5033 }
5034
5035 EAPI void
5036 elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item           *it,
5037                                         Elm_Tooltip_Item_Content_Cb func,
5038                                         const void                 *data,
5039                                         Evas_Smart_Cb               del_cb)
5040 {
5041    ELM_OBJ_ITEM_CHECK_OR_GOTO(it, error);
5042    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5043
5044    if ((_it->tooltip.content_cb == func) && (_it->tooltip.data == data))
5045      return;
5046
5047    if (_it->tooltip.del_cb)
5048      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(it), it);
5049
5050    _it->tooltip.content_cb = func;
5051    _it->tooltip.data = data;
5052    _it->tooltip.del_cb = del_cb;
5053
5054    if (VIEW(_it))
5055      {
5056         elm_widget_item_tooltip_content_cb_set(_it,
5057                                                _it->tooltip.content_cb,
5058                                                _it->tooltip.data, NULL);
5059         elm_widget_item_tooltip_style_set(_it, _it->tooltip.style);
5060         elm_widget_item_tooltip_window_mode_set(_it, _it->tooltip.free_size);
5061      }
5062
5063    return;
5064
5065 error:
5066    if (del_cb) del_cb((void *)data, NULL, NULL);
5067 }
5068
5069 EAPI void
5070 elm_genlist_item_tooltip_unset(Elm_Object_Item *it)
5071 {
5072    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5073    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5074
5075    if ((VIEW(_it)) && (_it->tooltip.content_cb))
5076      elm_widget_item_tooltip_unset(_it);
5077
5078    if (_it->tooltip.del_cb)
5079      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(_it), _it);
5080    _it->tooltip.del_cb = NULL;
5081    _it->tooltip.content_cb = NULL;
5082    _it->tooltip.data = NULL;
5083    _it->tooltip.free_size = EINA_FALSE;
5084    if (_it->tooltip.style)
5085      elm_genlist_item_tooltip_style_set(it, NULL);
5086 }
5087
5088 EAPI void
5089 elm_genlist_item_tooltip_style_set(Elm_Object_Item  *it,
5090                                    const char       *style)
5091 {
5092    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5093    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5094
5095    eina_stringshare_replace(&_it->tooltip.style, style);
5096    if (VIEW(_it)) elm_widget_item_tooltip_style_set(_it, style);
5097 }
5098
5099 EAPI const char *
5100 elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
5101 {
5102    return elm_object_item_tooltip_style_get(it);
5103 }
5104
5105 EAPI Eina_Bool
5106 elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *it,
5107                                          Eina_Bool disable)
5108 {
5109    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5110    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5111
5112    _it->tooltip.free_size = disable;
5113    if (VIEW(_it)) return elm_widget_item_tooltip_window_mode_set(_it, disable);
5114    return EINA_TRUE;
5115 }
5116
5117 EAPI Eina_Bool
5118 elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *it)
5119 {
5120    return elm_object_tooltip_window_mode_get(VIEW(it));
5121 }
5122
5123 EAPI void
5124 elm_genlist_item_cursor_set(Elm_Object_Item  *it,
5125                             const char       *cursor)
5126 {
5127    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5128    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5129    eina_stringshare_replace(&_it->mouse_cursor, cursor);
5130    if (VIEW(_it)) elm_widget_item_cursor_set(_it, cursor);
5131 }
5132
5133 EAPI const char *
5134 elm_genlist_item_cursor_get(const Elm_Object_Item *it)
5135 {
5136    return elm_widget_item_cursor_get(it);
5137 }
5138
5139 EAPI void
5140 elm_genlist_item_cursor_unset(Elm_Object_Item *it)
5141 {
5142    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5143    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5144
5145    if (!_it->mouse_cursor) return;
5146
5147    if (VIEW(_it)) elm_widget_item_cursor_unset(_it);
5148
5149    eina_stringshare_del(_it->mouse_cursor);
5150    _it->mouse_cursor = NULL;
5151 }
5152
5153 EAPI void
5154 elm_genlist_item_cursor_style_set(Elm_Object_Item  *it,
5155                                   const char       *style)
5156 {
5157    elm_widget_item_cursor_style_set(it, style);
5158 }
5159
5160 EAPI const char *
5161 elm_genlist_item_cursor_style_get(const Elm_Object_Item *it)
5162 {
5163    return elm_widget_item_cursor_style_get(it);
5164 }
5165
5166 EAPI void
5167 elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *it,
5168                                         Eina_Bool        engine_only)
5169 {
5170    elm_widget_item_cursor_engine_only_set(it, engine_only);
5171 }
5172
5173 EAPI Eina_Bool
5174 elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it)
5175 {
5176    return elm_widget_item_cursor_engine_only_get(it);
5177 }
5178
5179 EAPI int
5180 elm_genlist_item_index_get(const Elm_Object_Item *it)
5181 {
5182    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, -1);
5183    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5184
5185    if (_it->item->block)
5186      return _it->position + (_it->item->block->position * _it->wd->max_items_per_block);
5187    return -1;
5188 }
5189
5190 EAPI void
5191 elm_genlist_mode_set(Evas_Object  *obj,
5192                      Elm_List_Mode mode)
5193 {
5194    ELM_CHECK_WIDTYPE(obj, widtype);
5195    Widget_Data *wd = elm_widget_data_get(obj);
5196    if (!wd) return;
5197    if (wd->mode == mode) return;
5198    wd->mode = mode;
5199    if (wd->mode == ELM_LIST_COMPRESS)
5200      elm_genlist_homogeneous_set(obj, EINA_FALSE);
5201    _sizing_eval(obj);
5202 }
5203
5204
5205 EAPI Elm_List_Mode
5206 elm_genlist_mode_get(const Evas_Object *obj)
5207 {
5208    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
5209    Widget_Data *wd = elm_widget_data_get(obj);
5210    if (!wd) return ELM_LIST_LAST;
5211    return wd->mode;
5212 }
5213
5214 EAPI void
5215 elm_genlist_bounce_set(Evas_Object *obj,
5216                        Eina_Bool    h_bounce,
5217                        Eina_Bool    v_bounce)
5218 {
5219    ELM_CHECK_WIDTYPE(obj, widtype);
5220    Widget_Data *wd = elm_widget_data_get(obj);
5221    if (!wd) return;
5222    wd->h_bounce = !!h_bounce;
5223    wd->v_bounce = !!v_bounce;
5224    elm_smart_scroller_bounce_allow_set(wd->scr, wd->h_bounce, wd->v_bounce);
5225 }
5226
5227 EAPI void
5228 elm_genlist_bounce_get(const Evas_Object *obj,
5229                        Eina_Bool         *h_bounce,
5230                        Eina_Bool         *v_bounce)
5231 {
5232    ELM_CHECK_WIDTYPE(obj, widtype);
5233    Widget_Data *wd = elm_widget_data_get(obj);
5234    if (!wd) return;
5235    if (h_bounce) *h_bounce = wd->h_bounce;
5236    if (v_bounce) *v_bounce = wd->v_bounce;
5237 }
5238
5239 EAPI void
5240 elm_genlist_homogeneous_set(Evas_Object *obj,
5241                             Eina_Bool    homogeneous)
5242 {
5243    ELM_CHECK_WIDTYPE(obj, widtype);
5244    Widget_Data *wd = elm_widget_data_get(obj);
5245    if (!wd) return;
5246    wd->homogeneous = !!homogeneous;
5247 }
5248
5249 EAPI Eina_Bool
5250 elm_genlist_homogeneous_get(const Evas_Object *obj)
5251 {
5252    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5253    Widget_Data *wd = elm_widget_data_get(obj);
5254    if (!wd) return EINA_FALSE;
5255    return wd->homogeneous;
5256 }
5257
5258 EAPI void
5259 elm_genlist_block_count_set(Evas_Object *obj,
5260                             int          count)
5261 {
5262    ELM_CHECK_WIDTYPE(obj, widtype);
5263    Widget_Data *wd = elm_widget_data_get(obj);
5264    if (!wd) return;
5265    wd->max_items_per_block = count;
5266    wd->item_cache_max = wd->max_items_per_block * 2;
5267    _item_cache_clean(wd);
5268 }
5269
5270 EAPI int
5271 elm_genlist_block_count_get(const Evas_Object *obj)
5272 {
5273    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5274    Widget_Data *wd = elm_widget_data_get(obj);
5275    if (!wd) return 0;
5276    return wd->max_items_per_block;
5277 }
5278
5279 EAPI void
5280 elm_genlist_longpress_timeout_set(Evas_Object *obj,
5281                                   double       timeout)
5282 {
5283    ELM_CHECK_WIDTYPE(obj, widtype);
5284    Widget_Data *wd = elm_widget_data_get(obj);
5285    if (!wd) return;
5286    wd->longpress_timeout = timeout;
5287 }
5288
5289 EAPI double
5290 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
5291 {
5292    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5293    Widget_Data *wd = elm_widget_data_get(obj);
5294    if (!wd) return 0;
5295    return wd->longpress_timeout;
5296 }
5297
5298 EAPI void
5299 elm_genlist_scroller_policy_set(Evas_Object        *obj,
5300                                 Elm_Scroller_Policy policy_h,
5301                                 Elm_Scroller_Policy policy_v)
5302 {
5303    ELM_CHECK_WIDTYPE(obj, widtype);
5304    Widget_Data *wd = elm_widget_data_get(obj);
5305    if ((!wd) || (!wd->scr)) return;
5306    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
5307        (policy_v >= ELM_SCROLLER_POLICY_LAST))
5308      return;
5309    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
5310 }
5311
5312 EAPI void
5313 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
5314                                 Elm_Scroller_Policy *policy_h,
5315                                 Elm_Scroller_Policy *policy_v)
5316 {
5317    ELM_CHECK_WIDTYPE(obj, widtype);
5318    Widget_Data *wd = elm_widget_data_get(obj);
5319    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
5320    if ((!wd) || (!wd->scr)) return;
5321    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
5322    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
5323    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
5324 }
5325
5326 EAPI void
5327 elm_genlist_realized_items_update(Evas_Object *obj)
5328 {
5329    ELM_CHECK_WIDTYPE(obj, widtype);
5330
5331    Eina_List *list, *l;
5332    Elm_Object_Item *it;
5333
5334    list = elm_genlist_realized_items_get(obj);
5335    EINA_LIST_FOREACH(list, l, it)
5336      elm_genlist_item_update(it);
5337 }
5338
5339 EAPI void
5340 elm_genlist_item_decorate_mode_set(Elm_Object_Item  *it,
5341                                    const char       *decorate_type,
5342                                    Eina_Bool         mode_set)
5343 {
5344    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5345    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5346
5347    Widget_Data *wd = _it->wd;
5348    Eina_List *l;
5349    Elm_Object_Item *it2;
5350
5351    if (!wd) return;
5352    if (!decorate_type) return;
5353    if ((_it->generation < _it->wd->generation) ||
5354        elm_widget_item_disabled_get(_it)) return;
5355    if (wd->decorate_mode) return;
5356
5357    if ((wd->mode_item == _it) &&
5358        (!strcmp(decorate_type, wd->decorate_type)) &&
5359        (mode_set))
5360       return;
5361    if (!_it->itc->decorate_item_style) return;
5362    _it->mode_set = mode_set;
5363
5364    if (wd->multi)
5365      {
5366         EINA_LIST_FOREACH(wd->selected, l, it2)
5367           if (((Elm_Gen_Item *)it2)->realized)
5368             elm_genlist_item_selected_set(it2, EINA_FALSE);
5369      }
5370    else
5371      {
5372         it2 = elm_genlist_selected_item_get(wd->obj);
5373         if ((it2) && (((Elm_Gen_Item *)it2)->realized))
5374           elm_genlist_item_selected_set(it2, EINA_FALSE);
5375      }
5376
5377    if (((wd->decorate_type) && (strcmp(decorate_type, wd->decorate_type))) ||
5378        (mode_set) ||
5379        ((_it == wd->mode_item) && (!mode_set)))
5380      _item_mode_unset(wd);
5381
5382    eina_stringshare_replace(&wd->decorate_type, decorate_type);
5383    if (mode_set) _item_mode_set(_it);
5384 }
5385
5386 EAPI const char *
5387 elm_genlist_item_decorate_mode_get(const Elm_Object_Item *it)
5388 {
5389    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5390    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5391    return _it->wd->decorate_type;
5392 }
5393
5394 EAPI const Elm_Object_Item *
5395 elm_genlist_decorated_item_get(const Evas_Object *obj)
5396 {
5397    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5398    Widget_Data *wd = elm_widget_data_get(obj);
5399    if (!wd) return NULL;
5400    return (Elm_Object_Item *) wd->mode_item;
5401 }
5402
5403 EAPI Eina_Bool
5404 elm_genlist_decorate_mode_get(const Evas_Object *obj)
5405 {
5406    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5407    Widget_Data *wd = elm_widget_data_get(obj);
5408    if (!wd) return EINA_FALSE;
5409
5410    return wd->decorate_mode;
5411 }
5412
5413 EAPI void
5414 elm_genlist_decorate_mode_set(Evas_Object *obj, Eina_Bool decorated)
5415 {
5416    ELM_CHECK_WIDTYPE(obj, widtype);
5417    Eina_List *list, *l;
5418    Elm_Gen_Item *it;
5419
5420    Widget_Data *wd = elm_widget_data_get(obj);
5421    if (!wd) return;
5422    decorated = !!decorated;
5423    if (wd->decorate_mode == decorated) return;
5424    wd->decorate_mode = decorated;
5425
5426    list = elm_genlist_realized_items_get(obj);
5427    if (!wd->decorate_mode)
5428      {
5429         EINA_LIST_FOREACH(list, l, it)
5430           {
5431              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
5432                _decorate_mode_item_unrealize(it);
5433           }
5434         _item_cache_zero(wd);
5435      }
5436    else
5437      {
5438         EINA_LIST_FOREACH(list, l, it)
5439           {
5440              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
5441                {
5442                   if (it->selected) _item_unselect(it);
5443                   if (it->itc->decorate_all_item_style)
5444                      _decorate_mode_item_realize(it, EINA_TRUE);
5445                }
5446           }
5447      }
5448    if (wd->calc_job) ecore_job_del(wd->calc_job);
5449    wd->calc_job = ecore_job_add(_calc_job, wd);
5450 }
5451
5452 EAPI void
5453 elm_genlist_reorder_mode_set(Evas_Object *obj,
5454                              Eina_Bool    reorder_mode)
5455 {
5456    ELM_CHECK_WIDTYPE(obj, widtype);
5457    Widget_Data *wd = elm_widget_data_get(obj);
5458    if (!wd) return;
5459    wd->reorder_mode = !!reorder_mode;
5460 }
5461
5462 EAPI Eina_Bool
5463 elm_genlist_reorder_mode_get(const Evas_Object *obj)
5464 {
5465    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5466    Widget_Data *wd = elm_widget_data_get(obj);
5467    if (!wd) return EINA_FALSE;
5468    return wd->reorder_mode;
5469 }
5470
5471 EAPI Elm_Genlist_Item_Type
5472 elm_genlist_item_type_get(const Elm_Object_Item *it)
5473 {
5474    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_GENLIST_ITEM_MAX);
5475    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5476    return _it->item->type;
5477 }
5478
5479 EAPI Elm_Genlist_Item_Class *
5480 elm_genlist_item_class_new(void)
5481 {
5482    Elm_Genlist_Item_Class *itc;
5483
5484    itc = calloc(1, sizeof(Elm_Genlist_Item_Class));
5485    if (!itc)
5486      return NULL;
5487    itc->version = CLASS_ALLOCATED;
5488    itc->refcount = 1;
5489    itc->delete_me = EINA_FALSE;
5490
5491    return itc;
5492 }
5493
5494 EAPI void
5495 elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc)
5496 {
5497    if (itc && (itc->version == CLASS_ALLOCATED))
5498      {
5499         if (!itc->delete_me) itc->delete_me = EINA_TRUE;
5500         if (itc->refcount > 0) elm_genlist_item_class_unref(itc);
5501         else
5502           {
5503              itc->version = 0;
5504              free(itc);
5505           }
5506      }
5507 }
5508
5509 EAPI void
5510 elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc)
5511 {
5512    if (itc && (itc->version == CLASS_ALLOCATED))
5513      {
5514         itc->refcount++;
5515         if (itc->refcount == 0) itc->refcount--;
5516      }
5517 }
5518
5519 EAPI void
5520 elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc)
5521 {
5522    if (itc && (itc->version == CLASS_ALLOCATED))
5523      {
5524         if (itc->refcount > 0) itc->refcount--;
5525         if (itc->delete_me && (!itc->refcount))
5526           elm_genlist_item_class_free(itc);
5527      }
5528 }
5529
5530 void _flip_job(void *data)
5531 {
5532    Elm_Gen_Item *it = (Elm_Gen_Item *) data;
5533    _elm_genlist_item_unrealize(it, EINA_FALSE);
5534    if (it->selected) _item_unselect(it);
5535    it->flipped = EINA_TRUE;
5536    it->item->nocache = EINA_TRUE;
5537 }
5538
5539 EAPI void
5540 elm_genlist_item_flip_set(Elm_Object_Item *it,
5541                           Eina_Bool flip)
5542 {
5543    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5544    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5545
5546    flip = !!flip;
5547    if (_it->flipped == flip) return;
5548
5549    if (flip)
5550      {
5551         ecore_job_add(_flip_job, _it);
5552         if (_it->wd->calc_job) ecore_job_del(_it->wd->calc_job);
5553         _it->wd->calc_job = ecore_job_add(_calc_job, _it->wd);
5554      }
5555    else
5556      {
5557         _it->flipped = flip;
5558         _item_cache_zero(_it->wd);
5559         elm_genlist_item_update(it);
5560         _it->item->nocache = EINA_FALSE;
5561      }
5562 }
5563
5564 EAPI Eina_Bool
5565 elm_genlist_item_flip_get(const Elm_Object_Item *it)
5566 {
5567    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5568    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5569    return _it->flipped;
5570 }
5571
5572 EAPI void
5573 elm_genlist_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode)
5574 {
5575    ELM_CHECK_WIDTYPE(obj, widtype);
5576    Widget_Data *wd = elm_widget_data_get(obj);
5577    if (!wd) return;
5578    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
5579      return;
5580    if (wd->select_mode != mode)
5581      wd->select_mode = mode;
5582 }
5583
5584 EAPI Elm_Object_Select_Mode
5585 elm_genlist_select_mode_get(const Evas_Object *obj)
5586 {
5587    ELM_CHECK_WIDTYPE(obj, widtype) ELM_OBJECT_SELECT_MODE_MAX;
5588    Widget_Data *wd = elm_widget_data_get(obj);
5589    if (!wd) return ELM_OBJECT_SELECT_MODE_MAX;
5590    return wd->select_mode;
5591 }
5592
5593 EAPI void
5594 elm_genlist_highlight_mode_set(Evas_Object *obj,
5595                                Eina_Bool    highlight)
5596 {
5597    ELM_CHECK_WIDTYPE(obj, widtype);
5598    Widget_Data *wd = elm_widget_data_get(obj);
5599    if (!wd) return;
5600    wd->highlight = !!highlight;
5601 }
5602
5603 EAPI Eina_Bool
5604 elm_genlist_highlight_mode_get(const Evas_Object *obj)
5605 {
5606    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5607    Widget_Data *wd = elm_widget_data_get(obj);
5608    if (!wd) return EINA_FALSE;
5609    return wd->highlight;
5610 }
5611
5612 EAPI void
5613 elm_genlist_item_select_mode_set(Elm_Object_Item *it,
5614                                  Elm_Object_Select_Mode mode)
5615 {
5616    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5617    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5618    if (!_it) return;
5619    if (_it->generation < _it->wd->generation) return;
5620    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
5621      return;
5622    if (_it->select_mode != mode)
5623      _it->select_mode = mode;
5624
5625    if (_it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
5626      {
5627         _it->item->mincalcd = EINA_FALSE;
5628         _it->item->updateme = EINA_TRUE;
5629         if (_it->item->block) _it->item->block->updateme = EINA_TRUE;
5630         if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
5631         _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
5632      }
5633 }
5634
5635 EAPI Elm_Object_Select_Mode
5636 elm_genlist_item_select_mode_get(const Elm_Object_Item *it)
5637 {
5638    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_OBJECT_SELECT_MODE_MAX);
5639    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5640    if (!_it) return ELM_OBJECT_SELECT_MODE_MAX;
5641    return _it->select_mode;
5642 }
5643
5644 /* for gengrid as of now */
5645 void
5646 _elm_genlist_page_relative_set(Evas_Object *obj,
5647                                double       h_pagerel,
5648                                double       v_pagerel)
5649 {
5650    Evas_Coord pagesize_h;
5651    Evas_Coord pagesize_v;
5652
5653    ELM_CHECK_WIDTYPE(obj, widtype);
5654    Widget_Data *wd = elm_widget_data_get(obj);
5655    if (!wd) return;
5656
5657    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
5658    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
5659                                  pagesize_v);
5660 }
5661
5662 /* for gengrid as of now */
5663 void
5664 _elm_genlist_page_relative_get(const Evas_Object *obj,
5665                                double            *h_pagerel,
5666                                double            *v_pagerel)
5667 {
5668    ELM_CHECK_WIDTYPE(obj, widtype);
5669    Widget_Data *wd = elm_widget_data_get(obj);
5670    if (!wd) return;
5671
5672    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
5673 }
5674
5675 /* for gengrid as of now */
5676 void
5677 _elm_genlist_page_size_set(Evas_Object *obj,
5678                            Evas_Coord   h_pagesize,
5679                            Evas_Coord   v_pagesize)
5680 {
5681    double pagerel_h;
5682    double pagerel_v;
5683
5684    ELM_CHECK_WIDTYPE(obj, widtype);
5685    Widget_Data *wd = elm_widget_data_get(obj);
5686    if (!wd) return;
5687    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
5688    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
5689                                  v_pagesize);
5690 }
5691
5692 /* for gengrid as of now */
5693 void
5694 _elm_genlist_current_page_get(const Evas_Object *obj,
5695                               int               *h_pagenumber,
5696                               int               *v_pagenumber)
5697 {
5698    ELM_CHECK_WIDTYPE(obj, widtype);
5699    Widget_Data *wd = elm_widget_data_get(obj);
5700    if (!wd) return;
5701    elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
5702 }
5703
5704 /* for gengrid as of now */
5705 void
5706 _elm_genlist_last_page_get(const Evas_Object *obj,
5707                            int               *h_pagenumber,
5708                            int               *v_pagenumber)
5709 {
5710    ELM_CHECK_WIDTYPE(obj, widtype);
5711    Widget_Data *wd = elm_widget_data_get(obj);
5712    if (!wd) return;
5713    elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
5714 }
5715
5716 /* for gengrid as of now */
5717 void
5718 _elm_genlist_page_show(const Evas_Object *obj,
5719                        int                h_pagenumber,
5720                        int                v_pagenumber)
5721 {
5722    ELM_CHECK_WIDTYPE(obj, widtype);
5723    Widget_Data *wd = elm_widget_data_get(obj);
5724    if (!wd) return;
5725    elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
5726 }
5727
5728 /* for gengrid as of now */
5729 void
5730 _elm_genlist_page_bring_in(const Evas_Object *obj,
5731                            int                h_pagenumber,
5732                            int                v_pagenumber)
5733 {
5734    ELM_CHECK_WIDTYPE(obj, widtype);
5735    Widget_Data *wd = elm_widget_data_get(obj);
5736    if (!wd) return;
5737    elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
5738 }
5739
5740 void
5741 _elm_genlist_item_unrealize(Elm_Gen_Item *it,
5742                             Eina_Bool     calc)
5743 {
5744    Evas_Object *content;
5745
5746    if (!it->realized) return;
5747    if (it->wd->reorder_it == it) return;
5748
5749    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
5750    if (!calc)
5751      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
5752    if (it->long_timer)
5753      {
5754         ecore_timer_del(it->long_timer);
5755         it->long_timer = NULL;
5756      }
5757
5758    elm_widget_stringlist_free(it->texts);
5759    it->texts = NULL;
5760    elm_widget_stringlist_free(it->contents);
5761    it->contents = NULL;
5762    elm_widget_stringlist_free(it->states);
5763    it->states = NULL;
5764
5765    EINA_LIST_FREE(it->content_objs, content)
5766      evas_object_del(content);
5767
5768    it->unrealize_cb(it);
5769
5770    it->realized = EINA_FALSE;
5771    it->want_unrealize = EINA_FALSE;
5772    evas_event_thaw(evas_object_evas_get(WIDGET(it)));
5773    evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
5774 }
5775
5776 void
5777 _elm_genlist_item_del_notserious(Elm_Gen_Item *it)
5778 {
5779    elm_widget_item_pre_notify_del(it);
5780    it->generation = it->wd->generation - 1; /* This means that the item is deleted */
5781    if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
5782
5783    if (it->itc->func.del)
5784      it->itc->func.del((void *)it->base.data, WIDGET(it));
5785 }
5786
5787 void
5788 _elm_genlist_item_del_serious(Elm_Gen_Item *it)
5789 {
5790    _elm_genlist_item_del_notserious(it);
5791    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
5792    if (it->tooltip.del_cb)
5793      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
5794    it->wd->walking -= it->walking;
5795    if (it->long_timer) ecore_timer_del(it->long_timer);
5796    if (it->group)
5797      it->wd->group_items = eina_list_remove(it->wd->group_items, it);
5798
5799    if (it->wd->state)
5800      {
5801         eina_inlist_sorted_state_free(it->wd->state);
5802         it->wd->state = NULL;
5803      }
5804    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
5805    it->wd->calc_job = ecore_job_add(it->wd->calc_cb, it->wd);
5806    free(it->item);
5807
5808    it->item = NULL;
5809    if (it->wd->last_selected_item == (Elm_Object_Item *)it)
5810      it->wd->last_selected_item = NULL;
5811    it->wd->item_count--;
5812 }
5813
5814 EAPI void
5815 elm_genlist_tree_effect_enabled_set(Evas_Object *obj, Eina_Bool enabled)
5816 {
5817    ELM_CHECK_WIDTYPE(obj, widtype);
5818    Widget_Data *wd = elm_widget_data_get(obj);
5819    if (!wd) return;
5820    wd->tree_effect_enabled = !!enabled;
5821 }
5822
5823 EAPI Eina_Bool
5824 elm_genlist_tree_effect_enabled_get(const Evas_Object *obj)
5825 {
5826    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5827    Widget_Data *wd = elm_widget_data_get(obj);
5828    if (!wd) return EINA_FALSE;
5829    return wd->tree_effect_enabled;
5830 }
5831
5832 static Evas_Object*
5833 _create_tray_alpha_bg(const Evas_Object *obj)
5834 {
5835    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5836    Widget_Data *wd = elm_widget_data_get(obj);
5837    if (!wd) return NULL;
5838
5839    Evas_Object *bg = NULL;
5840    Evas_Coord ox, oy, ow, oh;
5841
5842    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
5843    bg  =  evas_object_rectangle_add(evas_object_evas_get(wd->obj));
5844    evas_object_color_set(bg,0,0,0,0);
5845    evas_object_resize(bg , ow, oh);
5846    evas_object_move(bg , ox, oy);
5847    return bg ;
5848 }
5849
5850 static void
5851 _item_contract_emit(Elm_Gen_Item *it)
5852 {
5853    Elm_Gen_Item *it2;
5854    Eina_List *l;
5855
5856    edje_object_signal_emit(VIEW(it), "elm,state,contract_flip", "");
5857    it->item->tree_effect_finished = EINA_FALSE;
5858
5859    EINA_LIST_FOREACH(it->item->items, l, it2)
5860      if (it2) _item_contract_emit(it2);
5861 }
5862
5863 static int
5864 _item_tree_effect_before(Elm_Gen_Item *it)
5865 {
5866    Elm_Gen_Item *it2;
5867    Eina_List *l;
5868
5869    EINA_LIST_FOREACH(it->item->items, l, it2)
5870      {
5871         if (it2->parent && (it == it2->parent))
5872           {
5873              if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
5874                edje_object_signal_emit(VIEW(it2), "elm,state,hide", "");
5875              else if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
5876                _item_contract_emit(it2);
5877           }
5878      }
5879    return ECORE_CALLBACK_CANCEL;
5880 }
5881
5882 static void
5883 _item_tree_effect(Widget_Data *wd, int y)
5884 {
5885    Elm_Gen_Item *it = NULL, *expanded_next_it;
5886
5887    expanded_next_it = wd->expanded_next_item;
5888
5889    if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
5890      {
5891         it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) expanded_next_it);
5892         while (it)
5893           {
5894              if (it->item->expanded_depth <= expanded_next_it->item->expanded_depth) break;
5895              if (it->item->scrl_y && (it->item->scrl_y < expanded_next_it->item->old_scrl_y + y) &&
5896                  (it->item->expanded_depth > expanded_next_it->item->expanded_depth))
5897                {
5898                   if (!it->item->tree_effect_finished)
5899                     {
5900                        edje_object_signal_emit(VIEW(it), "flip_item", "");
5901                        evas_object_show(VIEW(it));
5902                        it->item->tree_effect_finished = EINA_TRUE;
5903                     }
5904                }
5905              it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it);
5906           }
5907      }
5908    else if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
5909      {
5910         it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) expanded_next_it);
5911         while (it)
5912           {
5913              if ((it->item->scrl_y > expanded_next_it->item->old_scrl_y + y) &&
5914                  (it->item->expanded_depth > expanded_next_it->item->expanded_depth))
5915                {
5916                   if (!it->item->tree_effect_finished)
5917                     {
5918                        edje_object_signal_emit(VIEW(it), "elm,state,hide", "");
5919                        it->item->tree_effect_finished = EINA_TRUE;
5920                     }
5921                }
5922              else
5923                break;
5924              it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it);
5925           }
5926      }
5927 }
5928
5929 static void
5930 _item_tree_effect_finish(Widget_Data *wd)
5931 {
5932    Item_Block *itb;
5933    Elm_Gen_Item *it = NULL;
5934    const Eina_List *l;
5935
5936    if (wd->tree_effect_animator)
5937      {
5938         if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
5939            _item_subitems_clear(wd->expanded_item);
5940         EINA_INLIST_FOREACH(wd->blocks, itb)
5941           {
5942              EINA_LIST_FOREACH(itb->items, l, it)
5943                {
5944                   it->item->tree_effect_finished = EINA_TRUE;
5945                   it->item->old_scrl_y = it->item->scrl_y;
5946                }
5947           }
5948      }
5949    _item_auto_scroll(wd);
5950    evas_object_lower(wd->alpha_bg);
5951    evas_object_hide(wd->alpha_bg);
5952    wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
5953    if (wd->move_items) wd->move_items = eina_list_free(wd->move_items);
5954
5955    evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
5956    evas_object_smart_callback_call(wd->obj, SIG_TREE_EFFECT_FINISHED, NULL);
5957    evas_object_smart_changed(wd->pan_smart);
5958
5959    wd->tree_effect_animator = NULL;
5960 }
5961
5962 static Eina_Bool
5963 _tree_effect_animator_cb(void *data)
5964 {
5965    Widget_Data *wd = data;
5966    if (!wd) return EINA_FALSE;
5967    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
5968    Elm_Gen_Item *it = NULL, *it2, *expanded_next_it;
5969    const Eina_List *l;
5970    double effect_duration = 0.5, t;
5971    int y = 0, dy = 0, dh = 0;
5972    Eina_Bool end = EINA_FALSE, vis = EINA_TRUE;
5973    int in = 0;
5974
5975    t = ((0.0 > (t = ecore_time_get() - wd->start_time)) ? 0.0 : t);
5976    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
5977    evas_output_viewport_get(evas_object_evas_get(wd->pan_smart), &cvx, &cvy, &cvw, &cvh);
5978    if (t > effect_duration) end = EINA_TRUE;
5979
5980    // Below while statement is needed, when the genlist is resized.
5981    it2 = wd->expanded_item;
5982    while (it2 && vis)
5983      {
5984         evas_object_move(VIEW(it2), it2->item->scrl_x, it2->item->scrl_y);
5985         vis = (ELM_RECTS_INTERSECT(it2->item->scrl_x, it2->item->scrl_y, it2->item->w, it2->item->h,
5986                                    cvx, cvy, cvw, cvh));
5987         it2 = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it2);
5988      }
5989
5990    if (wd->expanded_next_item)
5991      {
5992         expanded_next_it = wd->expanded_next_item;
5993
5994         /* move items */
5995         EINA_LIST_FOREACH(wd->move_items, l, it)
5996           {
5997              if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
5998                {
5999                   expanded_next_it->item->old_scrl_y = wd->expanded_item->item->old_scrl_y + wd->expanded_item->item->h;
6000                   if (expanded_next_it->item->scrl_y < expanded_next_it->item->old_scrl_y) //did not calculate next item position
6001                     expanded_next_it->item->scrl_y = cvy + cvh;
6002
6003                   dy = ((expanded_next_it->item->scrl_y >= (cvy + cvh)) ?
6004                          cvy + cvh : expanded_next_it->item->scrl_y) -
6005                          expanded_next_it->item->old_scrl_y;
6006                }
6007              else if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6008                {
6009                   if (expanded_next_it->item->scrl_y > expanded_next_it->item->old_scrl_y) //did not calculate next item position
6010                      expanded_next_it->item->old_scrl_y = cvy + cvh;
6011
6012                   if (expanded_next_it->item->old_scrl_y > (cvy + cvh))
6013                     {
6014                        dy = (wd->expanded_item->item->scrl_y + wd->expanded_item->item->h) -
6015                        cvy + cvh;
6016                        expanded_next_it->item->old_scrl_y = cvy + cvh;
6017                     }
6018                   else
6019                     {
6020                        dy = (wd->expanded_item->item->scrl_y + wd->expanded_item->item->h) -
6021                              expanded_next_it->item->old_scrl_y;
6022                     }
6023                }
6024
6025              if (t <= effect_duration)
6026                {
6027                   y = ((1 - (1 - (t / effect_duration)) * (1 - (t /effect_duration))) * dy);
6028                }
6029              else
6030                {
6031                   end = EINA_TRUE;
6032                   y = dy;
6033                }
6034
6035              if (!it->realized)
6036                {
6037                   _item_realize(it, in, 0);
6038                }
6039              in++;
6040
6041              if (it != expanded_next_it)
6042                {
6043                   it->item->old_scrl_y = expanded_next_it->item->old_scrl_y + expanded_next_it->item->h + dh;
6044                   dh += it->item->h;
6045                }
6046
6047              if ((it->item->old_scrl_y + y) < (cvy + cvh))
6048                _item_position(it, VIEW(it),it->item->scrl_x, it->item->old_scrl_y + y);
6049           }
6050         /* tree effect */
6051         _item_tree_effect(wd, y);
6052      }
6053    else
6054      {
6055         int expanded_item_num = 0;
6056         int num = 0;
6057
6058         if (wd->expanded_item)
6059           it = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) wd->expanded_item);
6060
6061         it2 = it;
6062         while (it2)
6063           {
6064              expanded_item_num++;
6065              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
6066           }
6067
6068         while (it)
6069           {
6070              num++;
6071              if (wd->expanded_item->item->expanded_depth >= it->item->expanded_depth) break;
6072              if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6073                {
6074                   if (!it->item->tree_effect_finished)
6075                     {
6076                        if (t >= (((num - 1) * effect_duration) / expanded_item_num))
6077                          {
6078                             edje_object_signal_emit(VIEW(it), "flip_item", "");
6079                             evas_object_show(VIEW(it));
6080                             it->item->tree_effect_finished = EINA_TRUE;
6081                          }
6082                     }
6083                }
6084              it = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
6085           }
6086      }
6087
6088    if (end)
6089      {
6090         _item_tree_effect_finish(wd);
6091         return ECORE_CALLBACK_CANCEL;
6092      }
6093    return ECORE_CALLBACK_RENEW;
6094 }