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