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