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