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