c86072b38c3adb2ae018e9a0488c0f39e69d252c
[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 }
3031
3032 static void
3033 _pan_calculate(Evas_Object *obj)
3034 {
3035    Pan *sd = evas_object_smart_data_get(obj);
3036    Item_Block *itb;
3037    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
3038    int in = 0;
3039    Elm_Gen_Item *git;
3040    Eina_List *l;
3041
3042    if (!sd) return;
3043    evas_event_freeze(evas_object_evas_get(obj));
3044
3045    if (sd->wd->pan_changed)
3046      {
3047         _calc_job(sd->wd);
3048         sd->wd->pan_changed = EINA_FALSE;
3049      }
3050
3051    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
3052    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
3053    EINA_LIST_FOREACH(sd->wd->group_items, l, git)
3054      {
3055         git->item->want_realize = EINA_FALSE;
3056      }
3057
3058    if (sd->wd->tree_effect_enabled && (sd->wd->move_effect_mode != ELM_GENLIST_TREE_EFFECT_NONE))
3059      {
3060         if (!sd->wd->tree_effect_animator)
3061           {
3062              _item_tree_effect_before(sd->wd->expanded_item);
3063              evas_object_raise(sd->wd->alpha_bg);
3064              evas_object_show(sd->wd->alpha_bg);
3065              sd->wd->start_time = ecore_time_get();
3066              sd->wd->tree_effect_animator = ecore_animator_add(_tree_effect_animator_cb, sd->wd);
3067           }
3068      }
3069
3070    EINA_INLIST_FOREACH(sd->wd->blocks, itb)
3071      {
3072         itb->w = sd->wd->minw;
3073         if (ELM_RECTS_INTERSECT(itb->x - sd->wd->pan_x + ox,
3074                                 itb->y - sd->wd->pan_y + oy,
3075                                 itb->w, itb->h,
3076                                 cvx, cvy, cvw, cvh))
3077           {
3078              if ((!itb->realized) || (itb->changed))
3079                _item_block_realize(itb);
3080              _item_block_position(itb, in);
3081           }
3082         else
3083           {
3084              if (itb->realized) _item_block_unrealize(itb);
3085           }
3086         in += itb->count;
3087      }
3088    if ((!sd->wd->reorder_it) || (sd->wd->reorder_pan_move))
3089       _group_items_recalc(sd->wd);
3090    if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
3091      {
3092         if (sd->wd->pan_y != sd->wd->reorder_old_pan_y)
3093            sd->wd->reorder_pan_move = EINA_TRUE;
3094         else sd->wd->reorder_pan_move = EINA_FALSE;
3095         evas_object_raise(sd->wd->VIEW(reorder_it));
3096         sd->wd->reorder_old_pan_y = sd->wd->pan_y;
3097         sd->wd->start_time = ecore_loop_time_get();
3098      }
3099
3100    if (!sd->wd->tree_effect_enabled || (sd->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_NONE))
3101      _item_auto_scroll(sd->wd);
3102
3103    evas_event_thaw(evas_object_evas_get(obj));
3104    evas_event_thaw_eval(evas_object_evas_get(obj));
3105 }
3106
3107 static void
3108 _pan_move(Evas_Object *obj,
3109           Evas_Coord   x __UNUSED__,
3110           Evas_Coord   y __UNUSED__)
3111 {
3112    Pan *sd = evas_object_smart_data_get(obj);
3113
3114    if (!sd) return;
3115
3116    sd->wd->pan_changed = EINA_TRUE;
3117    evas_object_smart_changed(obj);
3118    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3119    sd->wd->calc_job = NULL;
3120 }
3121
3122 static void
3123 _hold_on(void        *data __UNUSED__,
3124          Evas_Object *obj,
3125          void        *event_info __UNUSED__)
3126 {
3127    Widget_Data *wd = elm_widget_data_get(obj);
3128    if (!wd) return;
3129    elm_smart_scroller_hold_set(wd->scr, 1);
3130 }
3131
3132 static void
3133 _hold_off(void        *data __UNUSED__,
3134           Evas_Object *obj,
3135           void        *event_info __UNUSED__)
3136 {
3137    Widget_Data *wd = elm_widget_data_get(obj);
3138    if (!wd) return;
3139    elm_smart_scroller_hold_set(wd->scr, 0);
3140 }
3141
3142 static void
3143 _freeze_on(void        *data __UNUSED__,
3144            Evas_Object *obj,
3145            void        *event_info __UNUSED__)
3146 {
3147    Widget_Data *wd = elm_widget_data_get(obj);
3148    if (!wd) return;
3149    elm_smart_scroller_freeze_set(wd->scr, 1);
3150 }
3151
3152 static void
3153 _freeze_off(void        *data __UNUSED__,
3154             Evas_Object *obj,
3155             void        *event_info __UNUSED__)
3156 {
3157    Widget_Data *wd = elm_widget_data_get(obj);
3158    if (!wd) return;
3159    elm_smart_scroller_freeze_set(wd->scr, 0);
3160 }
3161
3162 static void
3163 _scr_anim_start(void        *data,
3164                 Evas_Object *obj __UNUSED__,
3165                 void        *event_info __UNUSED__)
3166 {
3167    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
3168 }
3169
3170 static void
3171 _scr_anim_stop(void        *data,
3172                Evas_Object *obj __UNUSED__,
3173                void        *event_info __UNUSED__)
3174 {
3175    evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
3176 }
3177
3178 static void
3179 _scr_drag_start(void            *data,
3180                 Evas_Object     *obj __UNUSED__,
3181                 void            *event_info __UNUSED__)
3182 {
3183    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
3184 }
3185
3186 static void
3187 _scr_drag_stop(void            *data,
3188                Evas_Object     *obj __UNUSED__,
3189                void            *event_info __UNUSED__)
3190 {
3191    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
3192 }
3193
3194 static void
3195 _edge_left(void        *data,
3196            Evas_Object *scr __UNUSED__,
3197            void        *event_info __UNUSED__)
3198 {
3199    Evas_Object *obj = data;
3200    evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
3201 }
3202
3203 static void
3204 _edge_right(void        *data,
3205             Evas_Object *scr __UNUSED__,
3206             void        *event_info __UNUSED__)
3207 {
3208    Evas_Object *obj = data;
3209    evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
3210 }
3211
3212 static void
3213 _edge_top(void        *data,
3214           Evas_Object *scr __UNUSED__,
3215           void        *event_info __UNUSED__)
3216 {
3217    Evas_Object *obj = data;
3218    evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
3219 }
3220
3221 static void
3222 _edge_bottom(void        *data,
3223              Evas_Object *scr __UNUSED__,
3224              void        *event_info __UNUSED__)
3225 {
3226    Evas_Object *obj = data;
3227    evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
3228 }
3229
3230 static void
3231 _decorate_item_realize(Elm_Gen_Item *it)
3232 {
3233    char buf[1024];
3234
3235    if ((it->item->deco_it_view) || (it->generation < it->wd->generation)) return;
3236
3237    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3238    it->item->deco_it_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
3239    edje_object_scale_set(it->item->deco_it_view,
3240                          elm_widget_scale_get(WIDGET(it)) *
3241                          _elm_config->scale);
3242    evas_object_smart_member_add(it->item->deco_it_view, it->wd->pan_smart);
3243    elm_widget_sub_object_add(WIDGET(it), it->item->deco_it_view);
3244
3245    strncpy(buf, "item", sizeof(buf));
3246    if (it->wd->mode == ELM_LIST_COMPRESS)
3247      strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3248
3249    if (it->item->order_num_in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf));
3250    strncat(buf, "/", sizeof(buf) - strlen(buf));
3251    strncat(buf, it->itc->decorate_item_style, sizeof(buf) - strlen(buf));
3252
3253    _elm_theme_object_set(WIDGET(it), it->item->deco_it_view, "genlist", buf,
3254                          elm_widget_style_get(WIDGET(it)));
3255    edje_object_mirrored_set(it->item->deco_it_view,
3256                             elm_widget_mirrored_get(WIDGET(it)));
3257
3258    /* signal callback add */
3259    evas_object_event_callback_add(it->item->deco_it_view, EVAS_CALLBACK_MOUSE_DOWN,
3260                                   _mouse_down, it);
3261    evas_object_event_callback_add(it->item->deco_it_view, EVAS_CALLBACK_MOUSE_UP,
3262                                   _mouse_up, it);
3263    evas_object_event_callback_add(it->item->deco_it_view, EVAS_CALLBACK_MOUSE_MOVE,
3264                                   _mouse_move, it);
3265
3266    /* text_get, content_get, state_get */
3267    /* FIXME: If you see that assert, please notify us and we
3268       will clean our mess */
3269    assert(eina_list_count(it->item->deco_it_content_objs) == 0);
3270
3271    _item_text_realize(it, it->item->deco_it_view, &it->item->deco_it_texts, NULL);
3272    if (!it->item->deco_it_contents)
3273      it->item->deco_it_contents =
3274         elm_widget_stringlist_get(edje_object_data_get(it->item->deco_it_view, "contents"));
3275    it->item->deco_it_content_objs =
3276      _item_mode_content_realize(it, it->item->deco_it_view,
3277                                 &it->item->deco_it_contents, NULL,
3278                                 &it->item->deco_it_content_objs);
3279    _item_state_realize(it, it->item->deco_it_view, &it->item->deco_it_states, NULL);
3280    edje_object_part_swallow(it->item->deco_it_view,
3281                             edje_object_data_get(it->item->deco_it_view, "mode_part"),
3282                             VIEW(it));
3283
3284    it->want_unrealize = EINA_FALSE;
3285    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3286    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3287 }
3288
3289 static void
3290 _decorate_item_unrealize(Elm_Gen_Item *it)
3291 {
3292    Widget_Data *wd = it->wd;
3293    Evas_Object *content;
3294    if (!it->item->deco_it_view) return;
3295
3296    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3297    elm_widget_stringlist_free(it->item->deco_it_texts);
3298    it->item->deco_it_texts = NULL;
3299    elm_widget_stringlist_free(it->item->deco_it_contents);
3300    it->item->deco_it_contents = NULL;
3301    elm_widget_stringlist_free(it->item->deco_it_states);
3302
3303    EINA_LIST_FREE(it->item->deco_it_content_objs, content)
3304      evas_object_del(content);
3305
3306    edje_object_part_unswallow(it->item->deco_it_view, VIEW(it));
3307    evas_object_smart_member_add(VIEW(it), wd->pan_smart);
3308    evas_object_del(it->item->deco_it_view);
3309    it->item->deco_it_view = NULL;
3310
3311    if (wd->mode_item == it)
3312      wd->mode_item = NULL;
3313    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3314    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3315 }
3316
3317 static void
3318 _decorate_item_set(Elm_Gen_Item *it)
3319 {
3320    if (!it) return;
3321    Widget_Data *wd = it->wd;
3322    if (!wd) return;
3323    char buf[1024];
3324
3325    wd->mode_item = it;
3326    it->item->nocache_once = EINA_TRUE;
3327
3328    if (wd->scr_hold_timer)
3329      {
3330         ecore_timer_del(wd->scr_hold_timer);
3331         wd->scr_hold_timer = NULL;
3332      }
3333    elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
3334    wd->scr_hold_timer = ecore_timer_add(0.1, _scr_hold_timer_cb, wd);
3335
3336    evas_event_freeze(evas_object_evas_get(it->wd->obj));
3337    _decorate_item_realize(it);
3338    if (it->item->group_item)
3339      evas_object_raise(it->item->VIEW(group_item));
3340    _item_position(it, it->item->deco_it_view, it->item->scrl_x, it->item->scrl_y);
3341    evas_event_thaw(evas_object_evas_get(it->wd->obj));
3342    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3343
3344    snprintf(buf, sizeof(buf), "elm,state,%s,active", wd->decorate_it_type);
3345    edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
3346 }
3347
3348 static void
3349 _decorate_item_unset(Widget_Data *wd)
3350 {
3351    if (!wd) return;
3352    if (!wd->mode_item) return;
3353    char buf[1024], buf2[1024];
3354    Elm_Gen_Item *it;
3355
3356    it = wd->mode_item;
3357    it->item->nocache_once = EINA_TRUE;
3358
3359    snprintf(buf, sizeof(buf), "elm,state,%s,passive", wd->decorate_it_type);
3360    snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished", wd->decorate_it_type);
3361
3362    edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
3363    edje_object_signal_callback_add(it->item->deco_it_view, buf2, "elm", _decorate_item_finished_signal_cb, it);
3364
3365    wd->mode_item = NULL;
3366 }
3367
3368 static void
3369 _decorate_all_item_position(Elm_Gen_Item *it, int itx, int ity)
3370 {
3371    if ((!it) || (!it->wd->decorate_all_mode)) return;
3372    evas_object_resize(it->deco_all_view, it->item->w, it->item->h);
3373    evas_object_move(it->deco_all_view, itx, ity);
3374 }
3375
3376 static void
3377 _decorate_all_item_realize(Elm_Gen_Item *it, Eina_Bool effect_on)
3378 {
3379    char buf[1024];
3380    const char *stacking_even;
3381    const char *stacking;
3382
3383    if ((!it) || (it->item->decorate_all_item_realized) ||
3384        (it->generation < it->wd->generation))
3385      return;
3386
3387    it->deco_all_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
3388    edje_object_scale_set(it->deco_all_view, elm_widget_scale_get(WIDGET(it)) *
3389                          _elm_config->scale);
3390    evas_object_smart_member_add(it->deco_all_view, it->wd->pan_smart);
3391    elm_widget_sub_object_add(WIDGET(it), it->deco_all_view);
3392
3393    if (it->item->type & ELM_GENLIST_ITEM_TREE)
3394       strncpy(buf, "tree", sizeof(buf));
3395    else strncpy(buf, "item", sizeof(buf));
3396    if (it->wd->mode == ELM_LIST_COMPRESS)
3397       strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3398
3399    strncat(buf, "/", sizeof(buf) - strlen(buf));
3400    strncat(buf, it->itc->decorate_all_item_style, sizeof(buf) - strlen(buf));
3401
3402    _elm_theme_object_set(WIDGET(it),  it->deco_all_view, "genlist", buf,
3403                          elm_widget_style_get(WIDGET(it)));
3404
3405    stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
3406    if (!stacking_even) stacking_even = "above";
3407    it->item->stacking_even = !!strcmp("above", stacking_even);
3408
3409    stacking = edje_object_data_get(VIEW(it), "stacking");
3410    if (!stacking) stacking = "yes";
3411    it->item->nostacking = !!strcmp("yes", stacking);
3412
3413    edje_object_mirrored_set(it->deco_all_view,
3414                             elm_widget_mirrored_get(WIDGET(it)));
3415
3416    _elm_genlist_item_odd_even_update(it);
3417    _elm_genlist_item_state_update(it, NULL);
3418
3419    if (effect_on) edje_object_signal_emit(it->deco_all_view, "elm,state,decorate,enabled,effect", "elm");
3420    else edje_object_signal_emit(it->deco_all_view, "elm,state,decorate,enabled", "elm");
3421
3422    _item_mouse_callbacks_del(it, VIEW(it));
3423    _item_mouse_callbacks_add(it, it->deco_all_view);
3424
3425    _item_text_realize(it, it->deco_all_view, &it->item->deco_all_texts, NULL);
3426    if (it->flipped) edje_object_signal_emit(it->deco_all_view, "elm,state,flip,enabled", "elm");
3427    if (!it->item->deco_all_contents)
3428      it->item->deco_all_contents =
3429         elm_widget_stringlist_get(edje_object_data_get(it->deco_all_view, "contents"));
3430    it->item->deco_all_content_objs =
3431      _item_mode_content_realize(it, it->deco_all_view,
3432                                 &it->item->deco_all_contents, NULL,
3433                                 &it->item->deco_all_content_objs);
3434    _item_state_realize(it, it->deco_all_view, &it->item->deco_all_states, NULL);
3435    edje_object_part_swallow(it->deco_all_view, "elm.swallow.decorate.content", VIEW(it));
3436
3437    _decorate_all_item_position(it, it->item->scrl_x, it->item->scrl_y);
3438    evas_object_show(it->deco_all_view);
3439
3440    if (it->selected) edje_object_signal_emit(it->deco_all_view, "elm,state,selected", "elm");
3441
3442    it->item->decorate_all_item_realized = EINA_TRUE;
3443    it->want_unrealize = EINA_FALSE;
3444 }
3445
3446 static void
3447 _decorate_all_item_unrealize(Elm_Gen_Item *it)
3448 {
3449    Evas_Object *icon;
3450    if ((!it) || (!it->item->decorate_all_item_realized)) return;
3451
3452    edje_object_part_unswallow(it->deco_all_view, VIEW(it));
3453    evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
3454    elm_widget_sub_object_add(WIDGET(it), VIEW(it));
3455    _elm_genlist_item_odd_even_update(it);
3456    _elm_genlist_item_state_update(it, NULL);
3457
3458    evas_object_del(it->deco_all_view);
3459    it->deco_all_view = NULL;
3460    elm_widget_stringlist_free(it->item->deco_all_texts);
3461    it->item->deco_all_texts = NULL;
3462    elm_widget_stringlist_free(it->item->deco_all_contents);
3463    it->item->deco_all_contents = NULL;
3464    elm_widget_stringlist_free(it->item->deco_all_states);
3465    it->item->deco_all_states = NULL;
3466    EINA_LIST_FREE(it->item->deco_all_content_objs, icon)
3467      evas_object_del(icon);
3468    edje_object_message_signal_process(it->deco_all_view);
3469    _item_mouse_callbacks_del(it, it->deco_all_view);
3470    _item_mouse_callbacks_add(it, VIEW(it));
3471
3472    it->item->decorate_all_item_realized = EINA_FALSE;
3473 }
3474
3475 static void
3476 _item_auto_scroll(Widget_Data *wd)
3477 {
3478    if (!wd) return;
3479    Elm_Gen_Item  *tmp_item = NULL;
3480
3481    if ((wd->expanded_item) && (wd->auto_scroll_enabled))
3482      {
3483         tmp_item = eina_list_data_get(eina_list_last(wd->expanded_item->item->items));
3484         if (!tmp_item) return;
3485         wd->show_item = tmp_item;
3486         wd->bring_in = EINA_TRUE;
3487         wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
3488         if ((wd->show_item->item->queued) || (!wd->show_item->item->mincalcd))
3489           {
3490              wd->show_item->item->showme = EINA_TRUE;
3491              wd->auto_scroll_enabled = EINA_FALSE;
3492           }
3493         else
3494           _scroll_item(wd);
3495      }
3496 }
3497
3498 EAPI Evas_Object *
3499 elm_genlist_add(Evas_Object *parent)
3500 {
3501    Evas_Object *obj;
3502    Evas *e;
3503    Widget_Data *wd;
3504    Evas_Coord minw, minh;
3505    static Evas_Smart *smart = NULL;
3506
3507    if (!smart)
3508      {
3509         static Evas_Smart_Class sc;
3510
3511         evas_object_smart_clipped_smart_set(&_pan_sc);
3512         sc = _pan_sc;
3513         sc.name = "elm_genlist_pan";
3514         sc.version = EVAS_SMART_CLASS_VERSION;
3515         sc.add = _pan_add;
3516         sc.del = _pan_del;
3517         sc.resize = _pan_resize;
3518         sc.move = _pan_move;
3519         sc.calculate = _pan_calculate;
3520         if (!(smart = evas_smart_class_new(&sc))) return NULL;
3521      }
3522
3523    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3524
3525    ELM_SET_WIDTYPE(widtype, "genlist");
3526    ELM_GEN_SETUP(wd);
3527    elm_widget_type_set(obj, "genlist");
3528    elm_widget_sub_object_add(parent, obj);
3529    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
3530    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
3531    elm_widget_data_set(obj, wd);
3532    elm_widget_del_hook_set(obj, _del_hook);
3533    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
3534    elm_widget_theme_hook_set(obj, _theme_hook);
3535    elm_widget_can_focus_set(obj, EINA_TRUE);
3536    elm_widget_event_hook_set(obj, _event_hook);
3537    elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
3538    elm_widget_translate_hook_set(obj, _translate_hook);
3539
3540    wd->generation = 1;
3541    wd->scr = elm_smart_scroller_add(e);
3542    elm_smart_scroller_widget_set(wd->scr, obj);
3543    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
3544                                        elm_widget_style_get(obj));
3545    elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
3546                                        _elm_config->thumbscroll_bounce_enable);
3547    elm_widget_resize_object_set(obj, wd->scr);
3548
3549    evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
3550    evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
3551    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
3552    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
3553    evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
3554    evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
3555    evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
3556    evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
3557
3558    wd->obj = obj;
3559    wd->mode = ELM_LIST_SCROLL;
3560    wd->max_items_per_block = MAX_ITEMS_PER_BLOCK;
3561    wd->item_cache_max = wd->max_items_per_block * 2;
3562    wd->longpress_timeout = _elm_config->longpress_timeout;
3563    wd->highlight = EINA_TRUE;
3564
3565    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
3566    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
3567    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
3568    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
3569
3570    wd->pan_smart = evas_object_smart_add(e, smart);
3571    wd->pan = evas_object_smart_data_get(wd->pan_smart);
3572    wd->pan->wd = wd;
3573
3574    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
3575                                      _pan_set, _pan_get, _pan_max_get,
3576                                      _pan_min_get, _pan_child_size_get);
3577
3578    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
3579                              &minw, &minh);
3580    evas_object_size_hint_min_set(obj, minw, minh);
3581
3582    evas_object_smart_callbacks_descriptions_set(obj, _signals);
3583
3584    _mirrored_set(obj, elm_widget_mirrored_get(obj));
3585    _sizing_eval(obj);
3586    return obj;
3587 }
3588
3589 void
3590 _item_select(Elm_Gen_Item *it)
3591 {
3592    Evas_Object *obj = WIDGET(it);
3593
3594    if ((it->generation < it->wd->generation) || (it->decorate_it_set) ||
3595        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
3596        (it->wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE))
3597      return;
3598    if (!it->selected)
3599      {
3600         it->selected = EINA_TRUE;
3601         it->wd->selected = eina_list_append(it->wd->selected, it);
3602      }
3603    else if (it->wd->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS) return;
3604
3605    evas_object_ref(obj);
3606    it->walking++;
3607    it->wd->walking++;
3608    if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), it);
3609    if (it->generation == it->wd->generation)
3610      evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
3611    it->walking--;
3612    it->wd->walking--;
3613    if ((it->wd->clear_me) && (!it->wd->walking))
3614      _elm_genlist_clear(WIDGET(it), EINA_TRUE);
3615    else
3616      {
3617         if ((!it->walking) && (it->generation < it->wd->generation))
3618           {
3619              if (!it->relcount)
3620                {
3621                   it->del_cb(it);
3622                   elm_widget_item_free(it);
3623                }
3624           }
3625         else
3626           it->wd->last_selected_item = (Elm_Object_Item *)it;
3627      }
3628    evas_object_unref(obj);
3629 }
3630
3631 static Evas_Object *
3632 _item_content_get_hook(Elm_Gen_Item *it, const char *part)
3633 {
3634    return edje_object_part_swallow_get(VIEW(it), part);
3635 }
3636
3637 static const char *
3638 _item_text_get_hook(Elm_Gen_Item *it, const char *part)
3639 {
3640    if (!it->itc->func.text_get) return NULL;
3641    return edje_object_part_text_get(VIEW(it), part);
3642 }
3643
3644 static void
3645 _item_disable_hook(Elm_Object_Item *it)
3646 {
3647    Eina_List *l;
3648    Evas_Object *obj;
3649    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
3650
3651    if (_it->generation < _it->wd->generation) return;
3652
3653    if (_it->selected)
3654      elm_genlist_item_selected_set(it, EINA_FALSE);
3655
3656    if (_it->realized)
3657      {
3658         if (elm_widget_item_disabled_get(it))
3659           {
3660              edje_object_signal_emit(VIEW(_it), "elm,state,disabled", "elm");
3661              if (_it->deco_all_view)
3662                edje_object_signal_emit(_it->deco_all_view, "elm,state,disabled", "elm");
3663           }
3664         else
3665           {
3666              edje_object_signal_emit(VIEW(_it), "elm,state,enabled", "elm");
3667              if (_it->deco_all_view)
3668                edje_object_signal_emit(_it->deco_all_view, "elm,state,enabled", "elm");
3669           }
3670         EINA_LIST_FOREACH(_it->content_objs, l, obj)
3671           elm_widget_disabled_set(obj, elm_widget_item_disabled_get(_it));
3672      }
3673 }
3674
3675 static Eina_Bool
3676 _item_del_pre_hook(Elm_Object_Item *it)
3677 {
3678    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
3679
3680    if ((_it->relcount > 0) || (_it->walking > 0))
3681      {
3682         elm_genlist_item_subitems_clear(it);
3683         if (_it->wd->show_item == _it) _it->wd->show_item = NULL;
3684         _elm_genlist_item_del_notserious(_it);
3685         if (_it->item->block)
3686           {
3687              if (_it->realized) _elm_genlist_item_unrealize(_it, EINA_FALSE);
3688              _it->item->block->changed = EINA_TRUE;
3689              if (_it->wd->calc_job) ecore_job_del(_it->wd->calc_job);
3690              _it->wd->calc_job = ecore_job_add(_calc_job, _it->wd);
3691           }
3692         if (_it->parent)
3693           {
3694              _it->parent->item->items =
3695                 eina_list_remove(_it->parent->item->items, it);
3696              _it->parent = NULL;
3697           }
3698         return EINA_FALSE;
3699      }
3700    _item_del(_it);
3701    return EINA_TRUE;
3702 }
3703
3704 static void
3705 _item_signal_emit_hook(Elm_Object_Item *it,
3706                        const char *emission,
3707                        const char *source)
3708 {
3709    edje_object_signal_emit(VIEW(it), emission, source);
3710 }
3711
3712 Elm_Gen_Item *
3713 _elm_genlist_item_new(Widget_Data              *wd,
3714                       const Elm_Gen_Item_Class *itc,
3715                       const void               *data,
3716                       Elm_Gen_Item             *parent,
3717                       Evas_Smart_Cb             func,
3718                       const void               *func_data)
3719 {
3720    Elm_Gen_Item *it;
3721
3722    it = elm_widget_item_new(wd->obj, Elm_Gen_Item);
3723    if (!it) return NULL;
3724    it->wd = wd;
3725    it->generation = wd->generation;
3726    it->itc = itc;
3727    elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)itc);
3728    it->base.data = data;
3729    it->parent = parent;
3730    it->func.func = func;
3731    it->func.data = func_data;
3732    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
3733    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
3734    elm_widget_item_disable_hook_set(it, _item_disable_hook);
3735    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
3736    elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
3737
3738    /* TEMPORARY */
3739    it->sel_cb = (Ecore_Cb)_item_select;
3740
3741    return it;
3742 }
3743
3744 static Elm_Gen_Item *
3745 _item_new(Widget_Data                  *wd,
3746           const Elm_Genlist_Item_Class *itc,
3747           const void                   *data,
3748           Elm_Gen_Item                 *parent,
3749           Elm_Genlist_Item_Type         type,
3750           Evas_Smart_Cb                 func,
3751           const void                   *func_data)
3752 {
3753    Elm_Gen_Item *it, *it2;
3754    int depth = 0;
3755
3756    it = _elm_genlist_item_new(wd, itc, data, parent, func, func_data);
3757    if (!it) return NULL;
3758    it->item = ELM_NEW(Elm_Gen_Item_Type);
3759    it->item->type = type;
3760    if (type & ELM_GENLIST_ITEM_GROUP) it->group++;
3761    it->item->expanded_depth = 0;
3762    ELM_GEN_ITEM_SETUP(it);
3763    if (it->parent)
3764      {
3765         if (it->parent->group)
3766           it->item->group_item = parent;
3767         else if (it->parent->item->group_item)
3768           it->item->group_item = it->parent->item->group_item;
3769      }
3770    for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
3771      {
3772         if (!it2->parent->group) depth += 1;
3773      }
3774    it->item->expanded_depth = depth;
3775    wd->item_count++;
3776    return it;
3777 }
3778
3779 static Item_Block *
3780 _item_block_new(Widget_Data *wd, Eina_Bool prepend)
3781 {
3782    Item_Block *itb;
3783
3784    itb = calloc(1, sizeof(Item_Block));
3785    if (!itb) return NULL;
3786    itb->wd = wd;
3787    if (prepend)
3788      {
3789         wd->blocks = eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
3790         _item_block_position_update(wd->blocks, 0);
3791      }
3792    else
3793      {
3794         wd->blocks = eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3795         itb->position_update = EINA_TRUE;
3796         if (wd->blocks != EINA_INLIST_GET(itb))
3797           {
3798              itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
3799           }
3800         else
3801           {
3802              itb->position = 0;
3803           }
3804      }
3805    return itb;
3806 }
3807
3808 static Eina_Bool
3809 _item_block_add(Widget_Data *wd,
3810                 Elm_Gen_Item *it)
3811 {
3812    Item_Block *itb = NULL;
3813
3814    if (!it->item->rel)
3815      {
3816 newblock:
3817         if (it->item->rel)
3818           {
3819              itb = calloc(1, sizeof(Item_Block));
3820              if (!itb) return EINA_FALSE;
3821              itb->wd = wd;
3822              if (!it->item->rel->item->block)
3823                {
3824                   wd->blocks =
3825                     eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3826                   itb->items = eina_list_append(itb->items, it);
3827                   itb->position_update = EINA_TRUE;
3828                   it->position = eina_list_count(itb->items);
3829                   it->position_update = EINA_TRUE;
3830
3831                   if (wd->blocks != EINA_INLIST_GET(itb))
3832                     {
3833                        itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
3834                     }
3835                   else
3836                     {
3837                        itb->position = 0;
3838                     }
3839                }
3840              else
3841                {
3842                   Eina_List *tmp;
3843
3844                   tmp = eina_list_data_find_list(itb->items, it->item->rel);
3845                   if (it->item->before)
3846                     {
3847                        wd->blocks = eina_inlist_prepend_relative
3848                            (wd->blocks, EINA_INLIST_GET(itb),
3849                            EINA_INLIST_GET(it->item->rel->item->block));
3850                        itb->items =
3851                          eina_list_prepend_relative_list(itb->items, it, tmp);
3852
3853                        /* Update index from where we prepended */
3854                        _item_position_update(eina_list_prev(tmp), it->item->rel->position);
3855                        _item_block_position_update(EINA_INLIST_GET(itb),
3856                                                    it->item->rel->item->block->position);
3857                     }
3858                   else
3859                     {
3860                        wd->blocks = eina_inlist_append_relative
3861                            (wd->blocks, EINA_INLIST_GET(itb),
3862                            EINA_INLIST_GET(it->item->rel->item->block));
3863                        itb->items =
3864                          eina_list_append_relative_list(itb->items, it, tmp);
3865
3866                        /* Update block index from where we appended */
3867                        _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
3868                        _item_block_position_update(EINA_INLIST_GET(itb),
3869                                                    it->item->rel->item->block->position + 1);
3870                     }
3871                }
3872           }
3873         else
3874           {
3875              if (it->item->before)
3876                {
3877                   if (wd->blocks)
3878                     {
3879                        itb = (Item_Block *)(wd->blocks);
3880                        if (itb->count >= wd->max_items_per_block)
3881                          {
3882                             itb = _item_block_new(wd, EINA_TRUE);
3883                             if (!itb) return EINA_FALSE;
3884                          }
3885                     }
3886                   else
3887                     {
3888                        itb = _item_block_new(wd, EINA_TRUE);
3889                        if (!itb) return EINA_FALSE;
3890                     }
3891                   itb->items = eina_list_prepend(itb->items, it);
3892
3893                   _item_position_update(itb->items, 0);
3894                }
3895              else
3896                {
3897                   if (wd->blocks)
3898                     {
3899                        itb = (Item_Block *)(wd->blocks->last);
3900                        if (itb->count >= wd->max_items_per_block)
3901                          {
3902                             itb = _item_block_new(wd, EINA_FALSE);
3903                             if (!itb) return EINA_FALSE;
3904                          }
3905                     }
3906                   else
3907                     {
3908                        itb = _item_block_new(wd, EINA_FALSE);
3909                        if (!itb) return EINA_FALSE;
3910                     }
3911                   itb->items = eina_list_append(itb->items, it);
3912                   it->position = eina_list_count(itb->items);
3913                }
3914           }
3915      }
3916    else
3917      {
3918         Eina_List *tmp;
3919
3920         if (it->item->rel->item->queued)
3921           {
3922              /* NOTE: for a strange reason eina_list and eina_inlist don't have the same property
3923                 on sorted insertion order, so the queue is not always ordered like the item list.
3924                 This lead to issue where we depend on an item that is not yet created. As a quick
3925                 work around, we reschedule the calc of the item and stop reordering the list to
3926                 prevent any nasty issue to show up here.
3927               */
3928              wd->queue = eina_list_append(wd->queue, it);
3929              wd->requeued = EINA_TRUE;
3930              it->item->queued = EINA_TRUE;
3931              return EINA_FALSE;
3932           }
3933         itb = it->item->rel->item->block;
3934         if (!itb) goto newblock;
3935         tmp = eina_list_data_find_list(itb->items, it->item->rel);
3936         if (it->item->before)
3937           {
3938              itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
3939              _item_position_update(eina_list_prev(tmp), it->item->rel->position);
3940           }
3941         else
3942           {
3943              itb->items = eina_list_append_relative_list(itb->items, it, tmp);
3944              _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
3945           }
3946      }
3947    itb->count++;
3948    itb->changed = EINA_TRUE;
3949    it->item->block = itb;
3950    if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
3951    itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
3952    if (it->item->rel)
3953      {
3954         it->item->rel->relcount--;
3955         if ((it->item->rel->generation < it->wd->generation) && (!it->item->rel->relcount))
3956           {
3957              _item_del(it->item->rel);
3958              elm_widget_item_free(it->item->rel);
3959           }
3960         it->item->rel = NULL;
3961      }
3962    if (itb->count > itb->wd->max_items_per_block)
3963      {
3964         Item_Block *itb2;
3965         Elm_Gen_Item *it2;
3966         int newc;
3967         Eina_Bool done = EINA_FALSE;
3968
3969         newc = itb->count / 2;
3970
3971         if (EINA_INLIST_GET(itb)->prev)
3972           {
3973              Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
3974
3975              if (itbp->count + newc < wd->max_items_per_block / 2)
3976                {
3977                   /* moving items to previous block */
3978                   while ((itb->count > newc) && (itb->items))
3979                     {
3980                        it2 = eina_list_data_get(itb->items);
3981                        itb->items = eina_list_remove_list(itb->items, itb->items);
3982                        itb->count--;
3983
3984                        itbp->items = eina_list_append(itbp->items, it2);
3985                        it2->item->block = itbp;
3986                        itbp->count++;
3987                     }
3988
3989                   done = EINA_TRUE;
3990                }
3991           }
3992
3993         if (!done && EINA_INLIST_GET(itb)->next)
3994           {
3995              Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
3996
3997              if (itbn->count + newc < wd->max_items_per_block / 2)
3998                {
3999                   /* moving items to next block */
4000                   while ((itb->count > newc) && (itb->items))
4001                     {
4002                        Eina_List *l;
4003
4004                        l = eina_list_last(itb->items);
4005                        it2 = eina_list_data_get(l);
4006                        itb->items = eina_list_remove_list(itb->items, l);
4007                        itb->count--;
4008
4009                        itbn->items = eina_list_prepend(itbn->items, it2);
4010                        it2->item->block = itbn;
4011                        itbn->count++;
4012                     }
4013
4014                   done = EINA_TRUE;
4015                }
4016           }
4017
4018         if (!done)
4019           {
4020              /* moving items to new block */
4021              itb2 = calloc(1, sizeof(Item_Block));
4022              if (!itb2) return EINA_FALSE;
4023              itb2->wd = wd;
4024              wd->blocks =
4025                eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
4026                                            EINA_INLIST_GET(itb));
4027              itb2->changed = EINA_TRUE;
4028              while ((itb->count > newc) && (itb->items))
4029                {
4030                   Eina_List *l;
4031
4032                   l = eina_list_last(itb->items);
4033                   it2 = l->data;
4034                   itb->items = eina_list_remove_list(itb->items, l);
4035                   itb->count--;
4036
4037                   itb2->items = eina_list_prepend(itb2->items, it2);
4038                   it2->item->block = itb2;
4039                   itb2->count++;
4040                }
4041           }
4042      }
4043
4044    return EINA_TRUE;
4045 }
4046
4047 static int
4048 _queue_process(Widget_Data *wd)
4049 {
4050    int n;
4051    Eina_Bool showme = EINA_FALSE;
4052    double t0, t;
4053
4054    t0 = ecore_loop_time_get();
4055    //evas_event_freeze(evas_object_evas_get(wd->obj));
4056    for (n = 0; (wd->queue) && (n < 128); n++)
4057      {
4058         Elm_Gen_Item *it;
4059
4060         it = eina_list_data_get(wd->queue);
4061         wd->queue = eina_list_remove_list(wd->queue, wd->queue);
4062         it->item->queued = EINA_FALSE;
4063         if (!_item_block_add(wd, it)) continue;
4064         if (!wd->blocks)
4065           _item_block_realize(it->item->block);
4066         t = ecore_time_get();
4067         if (it->item->block->changed)
4068           {
4069              showme = _item_block_recalc(it->item->block, it->item->block->num, EINA_TRUE);
4070              it->item->block->changed = 0;
4071              if (wd->pan_changed)
4072                {
4073                   if (wd->calc_job) ecore_job_del(wd->calc_job);
4074                   wd->calc_job = NULL;
4075                   _calc_job(wd);
4076                   wd->pan_changed = EINA_FALSE;
4077                }
4078           }
4079         if (showme) it->item->block->showme = EINA_TRUE;
4080         /* same as eina_inlist_count > 1 */
4081         if (wd->blocks && wd->blocks->next)
4082           {
4083              if ((t - t0) > (ecore_animator_frametime_get())) break;
4084           }
4085      }
4086    //evas_event_thaw(evas_object_evas_get(wd->obj));
4087    //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4088    return n;
4089 }
4090
4091 static Eina_Bool
4092 _idle_process(void *data, Eina_Bool *wakeup)
4093 {
4094    Widget_Data *wd = data;
4095
4096    //xxx
4097    //static double q_start = 0.0;
4098    //if (q_start == 0.0) q_start = ecore_time_get();
4099    //xxx
4100    if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
4101    if (!wd->queue)
4102      {
4103         //xxx
4104         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
4105         //xxx
4106         return ECORE_CALLBACK_CANCEL;
4107      }
4108    return ECORE_CALLBACK_RENEW;
4109 }
4110
4111 static Eina_Bool
4112 _item_idle_enterer(void *data)
4113 {
4114    Widget_Data *wd = data;
4115    Eina_Bool wakeup = EINA_FALSE;
4116    Eina_Bool ok = _idle_process(data, &wakeup);
4117
4118    if (wakeup)
4119      {
4120         // wake up mainloop
4121         if (wd->calc_job) ecore_job_del(wd->calc_job);
4122         wd->calc_job = ecore_job_add(_calc_job, wd);
4123      }
4124    if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
4125    return ok;
4126 }
4127
4128 static void
4129 _item_queue(Widget_Data *wd,
4130             Elm_Gen_Item *it,
4131             Eina_Compare_Cb cb)
4132 {
4133    if (it->item->queued) return;
4134    it->item->queued = EINA_TRUE;
4135    if (cb && !wd->requeued)
4136      wd->queue = eina_list_sorted_insert(wd->queue, cb, it);
4137    else
4138      wd->queue = eina_list_append(wd->queue, it);
4139 // FIXME: why does a freeze then thaw here cause some genlist
4140 // elm_genlist_item_append() to be much much slower?
4141 //   evas_event_freeze(evas_object_evas_get(wd->obj));
4142    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
4143      {
4144         if (wd->queue_idle_enterer)
4145           {
4146              ecore_idle_enterer_del(wd->queue_idle_enterer);
4147              wd->queue_idle_enterer = NULL;
4148           }
4149         _queue_process(wd);
4150      }
4151 //   evas_event_thaw(evas_object_evas_get(wd->obj));
4152 //   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4153    if (!wd->queue_idle_enterer)
4154      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
4155 }
4156
4157 static int
4158 _elm_genlist_item_compare(const void *data, const void *data1)
4159 {
4160    const Elm_Gen_Item *it, *item1;
4161    it = ELM_GEN_ITEM_FROM_INLIST(data);
4162    item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
4163    return it->wd->item_compare_cb(it, item1);
4164 }
4165
4166 static int
4167 _elm_genlist_item_list_compare(const void *data, const void *data1)
4168 {
4169    const Elm_Gen_Item *it = data;
4170    const Elm_Gen_Item *item1 = data1;
4171    return it->wd->item_compare_cb(it, item1);
4172 }
4173
4174 /*If application want to know the relative item, use elm_genlist_item_prev_get(it)*/
4175 static void
4176 _item_move_after(Elm_Gen_Item *it, Elm_Gen_Item *after)
4177 {
4178    if (!it) return;
4179    if (!after) return;
4180
4181    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4182    _item_block_del(it);
4183
4184    it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
4185    it->item->rel = after;
4186    it->item->rel->relcount++;
4187    it->item->before = EINA_FALSE;
4188    if (after->item->group_item) it->item->group_item = after->item->group_item;
4189    _item_queue(it->wd, it, NULL);
4190
4191    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED_AFTER, it);
4192 }
4193
4194 /*If application want to know the relative item, use elm_genlist_item_next_get(it)*/
4195 static void
4196 _item_move_before(Elm_Gen_Item *it, Elm_Gen_Item *before)
4197 {
4198    if (!it) return;
4199    if (!before) return;
4200
4201    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4202    _item_block_del(it);
4203    it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
4204    it->item->rel = before;
4205    it->item->rel->relcount++;
4206    it->item->before = EINA_TRUE;
4207    if (before->item->group_item) it->item->group_item = before->item->group_item;
4208    _item_queue(it->wd, it, NULL);
4209
4210    evas_object_smart_callback_call(WIDGET(it), SIG_MOVED_BEFORE, it);
4211 }
4212
4213 EAPI unsigned int
4214 elm_genlist_items_count(const Evas_Object *obj)
4215 {
4216    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4217    Widget_Data *wd = elm_widget_data_get(obj);
4218    if (!wd) return 0;
4219    return wd->item_count;
4220 }
4221
4222 EAPI Elm_Object_Item *
4223 elm_genlist_item_append(Evas_Object                  *obj,
4224                         const Elm_Genlist_Item_Class *itc,
4225                         const void                   *data,
4226                         Elm_Object_Item              *parent,
4227                         Elm_Genlist_Item_Type         type,
4228                         Evas_Smart_Cb                 func,
4229                         const void                   *func_data)
4230 {
4231    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4232    Widget_Data *wd = elm_widget_data_get(obj);
4233    if (!wd) return NULL;
4234    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4235                                 func, func_data);
4236    if (!it) return NULL;
4237    if (!it->parent)
4238      {
4239         if (it->group)
4240           wd->group_items = eina_list_append(wd->group_items, it);
4241         wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
4242         it->item->rel = NULL;
4243      }
4244    else
4245      {
4246         Elm_Gen_Item *it2 = NULL;
4247         Eina_List *ll = eina_list_last(it->parent->item->items);
4248         if (ll) it2 = ll->data;
4249         it->parent->item->items = eina_list_append(it->parent->item->items, it);
4250         if (!it2) it2 = it->parent;
4251         wd->items =
4252           eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4253                                       EINA_INLIST_GET(it2));
4254         it->item->rel = it2;
4255         it->item->rel->relcount++;
4256      }
4257    it->item->before = EINA_FALSE;
4258    _item_queue(wd, it, NULL);
4259    return (Elm_Object_Item *)it;
4260 }
4261
4262 EAPI Elm_Object_Item *
4263 elm_genlist_item_prepend(Evas_Object                  *obj,
4264                          const Elm_Genlist_Item_Class *itc,
4265                          const void                   *data,
4266                          Elm_Object_Item              *parent,
4267                          Elm_Genlist_Item_Type         type,
4268                          Evas_Smart_Cb                 func,
4269                          const void                   *func_data)
4270 {
4271    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4272    Widget_Data *wd = elm_widget_data_get(obj);
4273    if (!wd) return NULL;
4274    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4275                                 func, func_data);
4276    if (!it) return NULL;
4277    if (!it->parent)
4278      {
4279         if (it->group)
4280           wd->group_items = eina_list_prepend(wd->group_items, it);
4281         wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
4282         it->item->rel = NULL;
4283      }
4284    else
4285      {
4286         Elm_Gen_Item *it2 = NULL;
4287         Eina_List *ll = it->parent->item->items;
4288         if (ll) it2 = ll->data;
4289         it->parent->item->items = eina_list_prepend(it->parent->item->items, it);
4290         if (!it2) it2 = it->parent;
4291         wd->items =
4292           eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4293                                        EINA_INLIST_GET(it2));
4294         it->item->rel = it2;
4295         it->item->rel->relcount++;
4296      }
4297    it->item->before = EINA_TRUE;
4298    _item_queue(wd, it, NULL);
4299    return (Elm_Object_Item *)it;
4300 }
4301
4302 EAPI Elm_Object_Item *
4303 elm_genlist_item_insert_after(Evas_Object                  *obj,
4304                               const Elm_Genlist_Item_Class *itc,
4305                               const void                   *data,
4306                               Elm_Object_Item              *parent,
4307                               Elm_Object_Item              *after,
4308                               Elm_Genlist_Item_Type         type,
4309                               Evas_Smart_Cb                 func,
4310                               const void                   *func_data)
4311 {
4312    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4313    ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
4314    Widget_Data *wd = elm_widget_data_get(obj);
4315    Elm_Gen_Item *_after = (Elm_Gen_Item *) after;
4316    if (!wd) return NULL;
4317    /* It makes no sense to insert after in an empty list with after != NULL, something really bad is happening in your app. */
4318    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4319
4320    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4321                                 func, func_data);
4322    if (!it) return NULL;
4323    if (!it->parent)
4324      {
4325         if ((it->group) && (_after->group))
4326           wd->group_items = eina_list_append_relative(wd->group_items, it,
4327                                                       _after);
4328      }
4329    else
4330      {
4331         it->parent->item->items =
4332            eina_list_append_relative(it->parent->item->items, it, _after);
4333      }
4334    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4335                                            EINA_INLIST_GET(_after));
4336    it->item->rel = _after;
4337    it->item->rel->relcount++;
4338    it->item->before = EINA_FALSE;
4339    _item_queue(wd, it, NULL);
4340    return (Elm_Object_Item *)it;
4341 }
4342
4343 EAPI Elm_Object_Item *
4344 elm_genlist_item_insert_before(Evas_Object                  *obj,
4345                                const Elm_Genlist_Item_Class *itc,
4346                                const void                   *data,
4347                                Elm_Object_Item              *parent,
4348                                Elm_Object_Item              *before,
4349                                Elm_Genlist_Item_Type         type,
4350                                Evas_Smart_Cb                 func,
4351                                const void                   *func_data)
4352 {
4353    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4354    ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
4355    Widget_Data *wd = elm_widget_data_get(obj);
4356    Elm_Gen_Item *_before = (Elm_Gen_Item *) before;
4357    if (!wd) return NULL;
4358    /* It makes no sense to insert before in an empty list with before != NULL, something really bad is happening in your app. */
4359    EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4360
4361    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4362                                 func, func_data);
4363    if (!it) return NULL;
4364    if (!it->parent)
4365      {
4366         if (it->group && _before->group)
4367           wd->group_items = eina_list_prepend_relative(wd->group_items, it,
4368                                                        _before);
4369      }
4370    else
4371      {
4372         it->parent->item->items =
4373            eina_list_prepend_relative(it->parent->item->items, it, _before);
4374      }
4375    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4376                                             EINA_INLIST_GET(_before));
4377    it->item->rel = _before;
4378    it->item->rel->relcount++;
4379    it->item->before = EINA_TRUE;
4380    _item_queue(wd, it, NULL);
4381    return (Elm_Object_Item *)it;
4382 }
4383
4384 EAPI Elm_Object_Item *
4385 elm_genlist_item_sorted_insert(Evas_Object                  *obj,
4386                                const Elm_Genlist_Item_Class *itc,
4387                                const void                   *data,
4388                                Elm_Object_Item              *parent,
4389                                Elm_Genlist_Item_Type         type,
4390                                Eina_Compare_Cb               comp,
4391                                Evas_Smart_Cb                 func,
4392                                const void                   *func_data)
4393 {
4394    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4395    Widget_Data *wd = elm_widget_data_get(obj);
4396    if (!wd) return NULL;
4397    Elm_Gen_Item *rel = NULL;
4398    Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4399                                 func, func_data);
4400    if (!it) return NULL;
4401
4402    wd->item_compare_cb = comp;
4403
4404    if (it->parent)
4405      {
4406         Eina_List *l;
4407         int cmp_result;
4408
4409         l = eina_list_search_sorted_near_list(it->parent->item->items,
4410                                               _elm_genlist_item_list_compare,
4411                                               it,
4412                                               &cmp_result);
4413         if (l)
4414           rel = eina_list_data_get(l);
4415         else
4416           rel = it->parent;
4417
4418         if (cmp_result >= 0)
4419           {
4420              it->parent->item->items = eina_list_prepend_relative_list(it->parent->item->items, it, l);
4421              wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4422              it->item->before = EINA_FALSE;
4423           }
4424         else if (cmp_result < 0)
4425           {
4426              it->parent->item->items = eina_list_append_relative_list(it->parent->item->items, it, l);
4427              wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4428              it->item->before = EINA_TRUE;
4429           }
4430      }
4431    else
4432      {
4433         if (!wd->state)
4434           {
4435              wd->state = eina_inlist_sorted_state_new();
4436              eina_inlist_sorted_state_init(wd->state, wd->items);
4437              wd->requeued = EINA_FALSE;
4438           }
4439
4440         if (it->group)
4441           wd->group_items = eina_list_append(wd->group_items, it);
4442
4443         wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
4444                                                     _elm_genlist_item_compare, wd->state);
4445
4446         if (EINA_INLIST_GET(it)->next)
4447           {
4448              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4449              it->item->before = EINA_TRUE;
4450           }
4451         else if (EINA_INLIST_GET(it)->prev)
4452           {
4453              rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4454              it->item->before = EINA_FALSE;
4455           }
4456      }
4457
4458    if (rel)
4459      {
4460         it->item->rel = rel;
4461         it->item->rel->relcount++;
4462      }
4463
4464    _item_queue(wd, it, _elm_genlist_item_list_compare);
4465
4466    return (Elm_Object_Item *)it;
4467 }
4468
4469 static void
4470 _elm_genlist_clear(Evas_Object *obj, Eina_Bool standby)
4471 {
4472    Eina_Inlist *next, *l;
4473    Widget_Data *wd = elm_widget_data_get(obj);
4474    if (!wd) return;
4475
4476    if (!standby) wd->generation++;
4477
4478    if (wd->state)
4479      {
4480         eina_inlist_sorted_state_free(wd->state);
4481         wd->state = NULL;
4482      }
4483
4484    if (wd->walking > 0)
4485      {
4486         wd->clear_me = EINA_TRUE;
4487         return;
4488      }
4489    evas_event_freeze(evas_object_evas_get(wd->obj));
4490    for (l = wd->items, next = l ? l->next : NULL;
4491         l;
4492         l = next, next = next ? next->next : NULL)
4493      {
4494         Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l);
4495
4496         if (it->generation < wd->generation)
4497           {
4498              Elm_Gen_Item *itn = NULL;
4499
4500              if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
4501              if (itn) itn->walking++; /* prevent early death of subitem */
4502              it->del_cb(it);
4503              elm_widget_item_free(it);
4504              if (itn) itn->walking--;
4505           }
4506      }
4507    wd->clear_me = EINA_FALSE;
4508    wd->pan_changed = EINA_TRUE;
4509    if (wd->calc_job)
4510      {
4511         ecore_job_del(wd->calc_job);
4512         wd->calc_job = NULL;
4513      }
4514    if (wd->selected) wd->selected = eina_list_free(wd->selected);
4515    if (wd->clear_cb) wd->clear_cb(wd);
4516    wd->pan_x = 0;
4517    wd->pan_y = 0;
4518    wd->minw = 0;
4519    wd->minh = 0;
4520
4521    if (wd->alpha_bg) evas_object_del(wd->alpha_bg);
4522    wd->alpha_bg = NULL;
4523
4524    if (wd->pan_smart)
4525      {
4526         evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
4527         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
4528      }
4529    if (wd->sizing_cb) wd->sizing_cb(wd->obj);
4530    elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
4531    evas_event_thaw(evas_object_evas_get(wd->obj));
4532    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4533 }
4534
4535 EAPI void
4536 elm_genlist_clear(Evas_Object *obj)
4537 {
4538    ELM_CHECK_WIDTYPE(obj, widtype);
4539    _elm_genlist_clear(obj, EINA_FALSE);
4540 }
4541
4542 EAPI void
4543 elm_genlist_multi_select_set(Evas_Object *obj,
4544                              Eina_Bool    multi)
4545 {
4546    ELM_CHECK_WIDTYPE(obj, widtype);
4547    Widget_Data *wd = elm_widget_data_get(obj);
4548    if (!wd) return;
4549    wd->multi = !!multi;
4550 }
4551
4552 EAPI Eina_Bool
4553 elm_genlist_multi_select_get(const Evas_Object *obj)
4554 {
4555    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4556    Widget_Data *wd = elm_widget_data_get(obj);
4557    if (!wd) return EINA_FALSE;
4558    return wd->multi;
4559 }
4560
4561 EAPI Elm_Object_Item *
4562 elm_genlist_selected_item_get(const Evas_Object *obj)
4563 {
4564    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4565    Widget_Data *wd = elm_widget_data_get(obj);
4566    if (!wd) return NULL;
4567    if (wd->selected) return wd->selected->data;
4568    return NULL;
4569 }
4570
4571 EAPI const Eina_List *
4572 elm_genlist_selected_items_get(const Evas_Object *obj)
4573 {
4574    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4575    Widget_Data *wd = elm_widget_data_get(obj);
4576    if (!wd) return NULL;
4577    return wd->selected;
4578 }
4579
4580 EAPI Eina_List *
4581 elm_genlist_realized_items_get(const Evas_Object *obj)
4582 {
4583    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4584    Widget_Data *wd = elm_widget_data_get(obj);
4585    Eina_List *list = NULL;
4586    Item_Block *itb;
4587    Eina_Bool done = EINA_FALSE;
4588    if (!wd) return NULL;
4589    EINA_INLIST_FOREACH(wd->blocks, itb)
4590      {
4591         if (itb->realized)
4592           {
4593              Eina_List *l;
4594              Elm_Gen_Item *it;
4595
4596              done = EINA_TRUE;
4597              EINA_LIST_FOREACH(itb->items, l, it)
4598                {
4599                   if (it->realized) list = eina_list_append(list, it);
4600                }
4601           }
4602         else
4603           {
4604              if (done) break;
4605           }
4606      }
4607    return list;
4608 }
4609
4610 EAPI Elm_Object_Item *
4611 elm_genlist_at_xy_item_get(const Evas_Object *obj,
4612                            Evas_Coord         x,
4613                            Evas_Coord         y,
4614                            int               *posret)
4615 {
4616    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4617    Widget_Data *wd = elm_widget_data_get(obj);
4618    Evas_Coord ox, oy, ow, oh;
4619    Item_Block *itb;
4620    Evas_Coord lasty;
4621    if (!wd) return NULL;
4622    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
4623    lasty = oy;
4624    EINA_INLIST_FOREACH(wd->blocks, itb)
4625      {
4626         Eina_List *l;
4627         Elm_Gen_Item *it;
4628
4629         if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
4630                                  oy + itb->y - itb->wd->pan_y,
4631                                  itb->w, itb->h, x, y, 1, 1))
4632           continue;
4633         EINA_LIST_FOREACH(itb->items, l, it)
4634           {
4635              Evas_Coord itx, ity;
4636
4637              itx = ox + itb->x + it->x - itb->wd->pan_x;
4638              ity = oy + itb->y + it->y - itb->wd->pan_y;
4639              if (ELM_RECTS_INTERSECT(itx, ity, it->item->w, it->item->h, x, y, 1, 1))
4640                {
4641                   if (posret)
4642                     {
4643                        if (y <= (ity + (it->item->h / 4))) *posret = -1;
4644                        else if (y >= (ity + it->item->h - (it->item->h / 4)))
4645                          *posret = 1;
4646                        else *posret = 0;
4647                     }
4648                   return (Elm_Object_Item *)it;
4649                }
4650              lasty = ity + it->item->h;
4651           }
4652      }
4653    if (posret)
4654      {
4655         if (y > lasty) *posret = 1;
4656         else *posret = -1;
4657      }
4658    return NULL;
4659 }
4660
4661 EAPI Elm_Object_Item *
4662 elm_genlist_first_item_get(const Evas_Object *obj)
4663 {
4664    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4665    Widget_Data *wd = elm_widget_data_get(obj);
4666    if (!wd) return NULL;
4667    if (!wd->items) return NULL;
4668    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
4669    while ((it) && (it->generation < wd->generation))
4670      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4671    return (Elm_Object_Item *)it;
4672 }
4673
4674 EAPI Elm_Object_Item *
4675 elm_genlist_last_item_get(const Evas_Object *obj)
4676 {
4677    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4678    Widget_Data *wd = elm_widget_data_get(obj);
4679    if (!wd) return NULL;
4680    if (!wd->items) return NULL;
4681    Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
4682    while ((it) && (it->generation < wd->generation))
4683      it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4684    return (Elm_Object_Item *)it;
4685 }
4686
4687 EAPI Elm_Object_Item *
4688 elm_genlist_item_next_get(const Elm_Object_Item *it)
4689 {
4690    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4691    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4692    while (_it)
4693      {
4694         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->next);
4695         if ((_it) && (_it->generation == _it->wd->generation)) break;
4696      }
4697    return (Elm_Object_Item *) _it;
4698 }
4699
4700 EAPI Elm_Object_Item *
4701 elm_genlist_item_prev_get(const Elm_Object_Item *it)
4702 {
4703    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4704    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4705    while (_it)
4706      {
4707         _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->prev);
4708         if ((_it) && (_it->generation == _it->wd->generation)) break;
4709      }
4710    return (Elm_Object_Item *) _it;
4711 }
4712
4713 EAPI Elm_Object_Item *
4714 elm_genlist_item_parent_get(const Elm_Object_Item *it)
4715 {
4716    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4717    return (Elm_Object_Item *) ((Elm_Gen_Item *)it)->parent;
4718 }
4719
4720 EAPI void
4721 elm_genlist_item_subitems_clear(Elm_Object_Item *it)
4722 {
4723    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4724    Widget_Data *wd = elm_widget_data_get(WIDGET(it));
4725    if (!wd) return;
4726    Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4727
4728    if (!wd->tree_effect_enabled || !wd->move_effect_mode)
4729      _item_subitems_clear(_it);
4730    else
4731      {
4732         if (!wd->tree_effect_animator)
4733           {
4734              wd->expanded_item = _it;
4735              _item_tree_effect_before(_it);
4736              evas_object_raise(wd->alpha_bg);
4737              evas_object_show(wd->alpha_bg);
4738              wd->start_time = ecore_time_get();
4739              wd->tree_effect_animator = ecore_animator_add(_tree_effect_animator_cb, wd);
4740           }
4741         else
4742            _item_subitems_clear(_it);
4743      }
4744 }
4745
4746 EAPI void
4747 elm_genlist_item_selected_set(Elm_Object_Item *it,
4748                               Eina_Bool selected)
4749 {
4750    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4751    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4752    Widget_Data *wd = _it->wd;
4753    if (!wd) return;
4754    if ((_it->generation < wd->generation) || elm_widget_item_disabled_get(_it))
4755      return;
4756    selected = !!selected;
4757    if (_it->selected == selected) return;
4758
4759    if (selected)
4760      {
4761         if (!wd->multi)
4762           {
4763              while (wd->selected)
4764                {
4765                   if (_it->unhighlight_cb) _it->unhighlight_cb(wd->selected->data);
4766                   _it->unsel_cb(wd->selected->data);
4767                }
4768           }
4769         _it->highlight_cb(_it);
4770         _item_select(_it);
4771         return;
4772      }
4773    if (_it->unhighlight_cb) _it->unhighlight_cb(_it);
4774    _it->unsel_cb(_it);
4775 }
4776
4777 EAPI Eina_Bool
4778 elm_genlist_item_selected_get(const Elm_Object_Item *it)
4779 {
4780    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4781    return ((Elm_Gen_Item *)it)->selected;
4782 }
4783
4784 Elm_Gen_Item *
4785 _elm_genlist_expanded_next_item_get(Elm_Gen_Item *it)
4786 {
4787    Elm_Gen_Item *it2;
4788    if (it->item->expanded)
4789      {
4790         it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
4791      }
4792    else
4793      {
4794         it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
4795         while (it2)
4796           {
4797              if (it->item->expanded_depth >= it2->item->expanded_depth) break;
4798              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
4799           }
4800      }
4801    return it2;
4802 }
4803
4804 static void
4805 _elm_genlist_move_items_set(Elm_Gen_Item *it)
4806 {
4807    Eina_List *l;
4808    Elm_Gen_Item *it2 = NULL;
4809    Evas_Coord ox, oy, ow, oh, dh = 0;
4810
4811    it->wd->expanded_next_item = _elm_genlist_expanded_next_item_get(it);
4812
4813    if (it->item->expanded)
4814      {
4815         it->wd->move_items = elm_genlist_realized_items_get(it->wd->obj);
4816         EINA_LIST_FOREACH(it->wd->move_items, l, it2)
4817           {
4818              if (it2 == it->wd->expanded_next_item) break;
4819              it->wd->move_items = eina_list_remove(it->wd->move_items, it2);
4820           }
4821      }
4822    else
4823      {
4824         evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
4825         it2 = it->wd->expanded_next_item;
4826         while (it2 && (dh < oy + oh))
4827           {
4828              dh += it2->item->h;
4829              it->wd->move_items = eina_list_append(it->wd->move_items, it2);
4830              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
4831           }
4832      }
4833 }
4834
4835 EAPI void
4836 elm_genlist_item_expanded_set(Elm_Object_Item  *it,
4837                               Eina_Bool         expanded)
4838 {
4839    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4840    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4841    expanded = !!expanded;
4842    if (_it->item->expanded == expanded) return;
4843    _it->item->expanded = expanded;
4844    _it->wd->expanded_item = _it;
4845    _elm_genlist_move_items_set(_it);
4846
4847    if (_it->wd->tree_effect_enabled && !_it->wd->alpha_bg)
4848       _it->wd->alpha_bg = _create_tray_alpha_bg(WIDGET(_it));
4849
4850    if (_it->item->expanded)
4851      {
4852         _it->wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_EXPAND;
4853         if (_it->realized)
4854           edje_object_signal_emit(VIEW(_it), "elm,state,expanded", "elm");
4855         evas_object_smart_callback_call(WIDGET(_it), SIG_EXPANDED, _it);
4856         _it->wd->auto_scroll_enabled = EINA_TRUE;
4857      }
4858    else
4859      {
4860         _it->wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_CONTRACT;
4861         if (_it->realized)
4862           edje_object_signal_emit(VIEW(_it), "elm,state,contracted", "elm");
4863         evas_object_smart_callback_call(WIDGET(_it), SIG_CONTRACTED, _it);
4864         _it->wd->auto_scroll_enabled = EINA_FALSE;
4865      }
4866 }
4867
4868 EAPI Eina_Bool
4869 elm_genlist_item_expanded_get(const Elm_Object_Item *it)
4870 {
4871    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4872    return ((Elm_Gen_Item *)it)->item->expanded;
4873 }
4874
4875 EAPI int
4876 elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it)
4877 {
4878    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
4879    return ((Elm_Gen_Item *)it)->item->expanded_depth;
4880 }
4881
4882 static Eina_Bool
4883 _elm_genlist_item_compute_coordinates(Elm_Object_Item *it,
4884                                       Elm_Genlist_Item_Scrollto_Type type,
4885                                       Eina_Bool bring_in,
4886                                       Evas_Coord *x,
4887                                       Evas_Coord *y,
4888                                       Evas_Coord *w,
4889                                       Evas_Coord *h)
4890 {
4891    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4892    Evas_Coord gith = 0;
4893    if (_it->generation < _it->wd->generation) return EINA_FALSE;
4894    if ((_it->item->queued) || (!_it->item->mincalcd))
4895      {
4896         _it->wd->show_item = _it;
4897         _it->wd->bring_in = bring_in;
4898         _it->wd->scrollto_type = type;
4899         _it->item->showme = EINA_TRUE;
4900         return EINA_FALSE;
4901      }
4902    if (_it->wd->show_item)
4903      {
4904         _it->wd->show_item->item->showme = EINA_FALSE;
4905         _it->wd->show_item = NULL;
4906      }
4907
4908    evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, w, h);
4909    switch (type)
4910      {
4911       case ELM_GENLIST_ITEM_SCROLLTO_IN:
4912          if ((_it->item->group_item) &&
4913              (_it->wd->pan_y > (_it->y + _it->item->block->y)))
4914           gith = _it->item->group_item->item->h;
4915          *h = _it->item->h;
4916          *y = _it->y + _it->item->block->y - gith;
4917          break;
4918       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
4919          if (_it->item->group_item) gith = _it->item->group_item->item->h;
4920          *y = _it->y + _it->item->block->y - gith;
4921          break;
4922       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
4923          *y = _it->y + _it->item->block->y - (*h / 2) + (_it->item->h / 2);
4924          break;
4925       default:
4926          return EINA_FALSE;
4927      }
4928
4929    *x = _it->x + _it->item->block->x;
4930    *w = _it->item->block->w;
4931    return EINA_TRUE;
4932 }
4933
4934 EAPI void
4935 elm_genlist_item_promote(Elm_Object_Item *it)
4936 {
4937    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4938    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4939    if (_it->generation < _it->wd->generation) return;
4940    _item_move_before(_it,
4941                      (Elm_Gen_Item *) elm_genlist_first_item_get(WIDGET(_it)));
4942 }
4943
4944 EAPI void
4945 elm_genlist_item_demote(Elm_Object_Item *it)
4946 {
4947    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4948    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4949    if (_it->generation < _it->wd->generation) return;
4950    _item_move_after(_it,
4951                     (Elm_Gen_Item *) elm_genlist_last_item_get(WIDGET(_it)));
4952 }
4953
4954 EAPI void
4955 elm_genlist_item_show(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
4956 {
4957    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4958    Evas_Coord x, y, w, h;
4959    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4960
4961    if (_elm_genlist_item_compute_coordinates(it, type, EINA_FALSE, &x, &y, &w, &h))
4962      elm_smart_scroller_child_region_show(_it->wd->scr, x, y, w, h);
4963 }
4964
4965 EAPI void
4966 elm_genlist_item_bring_in(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
4967 {
4968
4969    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4970    Evas_Coord x, y, w, h;
4971    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4972
4973    if (_elm_genlist_item_compute_coordinates(it, type, EINA_TRUE, &x, &y, &w, &h))
4974      elm_smart_scroller_region_bring_in(_it->wd->scr, x, y, w, h);
4975 }
4976
4977 EAPI void
4978 elm_genlist_item_all_contents_unset(Elm_Object_Item *it, Eina_List **l)
4979 {
4980    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4981
4982    Evas_Object *content;
4983    EINA_LIST_FREE(((Elm_Gen_Item *)it)->content_objs, content)
4984      {
4985         elm_widget_sub_object_del(WIDGET(it), content);
4986         evas_object_smart_member_del(content);
4987         evas_object_hide(content);
4988         if (l) *l = eina_list_append(*l, content);
4989      }
4990 }
4991
4992 EAPI void
4993 elm_genlist_item_update(Elm_Object_Item *it)
4994 {
4995    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4996    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4997
4998    if (!_it->item->block) return;
4999    if (_it->generation < _it->wd->generation) return;
5000    _it->item->mincalcd = EINA_FALSE;
5001    _it->item->updateme = EINA_TRUE;
5002    _it->item->block->updateme = EINA_TRUE;
5003    if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
5004    _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
5005 }
5006
5007 EAPI void
5008 elm_genlist_item_fields_update(Elm_Object_Item *it,
5009                                const char *parts,
5010                                Elm_Genlist_Item_Field_Type itf)
5011 {
5012    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5013    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5014
5015    if (!_it->item->block) return;
5016    if (_it->generation < _it->wd->generation) return;
5017
5018    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT))
5019      _item_text_realize(_it, VIEW(_it), &_it->texts, parts);
5020    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
5021      {
5022         _it->content_objs = _item_content_unrealize(_it, VIEW(_it),
5023                                                    &_it->contents, parts);
5024         _it->content_objs = _item_content_realize(_it, VIEW(_it),
5025                                                  &_it->contents, parts);
5026
5027         if (_it->flipped)
5028           {
5029              _it->item->flip_content_objs =
5030                _item_mode_content_unrealize(_it, VIEW(_it),
5031                                             &_it->item->flip_contents, parts,
5032                                             &_it->item->flip_content_objs);
5033              _it->item->flip_content_objs =
5034                _item_mode_content_realize(_it, VIEW(_it),
5035                                           &_it->item->flip_contents, parts,
5036                                           &_it->item->flip_content_objs);
5037           }
5038         if (_it->item->deco_it_view)
5039           {
5040              _it->item->deco_it_content_objs =
5041                _item_mode_content_unrealize(_it, _it->item->deco_it_view,
5042                                             &_it->item->deco_it_contents, parts,
5043                                             &_it->item->deco_it_content_objs);
5044              _it->item->deco_it_content_objs =
5045                _item_mode_content_realize(_it, _it->item->deco_it_view,
5046                                           &_it->item->deco_it_contents, parts,
5047                                           &_it->item->deco_it_content_objs);
5048           }
5049         if (_it->wd->decorate_all_mode)
5050           {
5051              _it->item->deco_all_content_objs =
5052                _item_mode_content_unrealize(_it, _it->deco_all_view,
5053                                             &_it->item->deco_all_contents, parts,
5054                                             &_it->item->deco_all_content_objs);
5055              _it->item->deco_all_content_objs =
5056                _item_mode_content_realize(_it, _it->deco_all_view,
5057                                           &_it->item->deco_all_contents, parts,
5058                                           &_it->item->deco_all_content_objs);
5059           }
5060      }
5061    if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
5062      _item_state_realize(_it, VIEW(_it), &_it->states, parts);
5063 }
5064
5065 EAPI void
5066 elm_genlist_item_item_class_update(Elm_Object_Item *it,
5067                                    const Elm_Genlist_Item_Class *itc)
5068 {
5069    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5070    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5071
5072    if (!_it->item->block) return;
5073    EINA_SAFETY_ON_NULL_RETURN(itc);
5074    if (_it->generation < _it->wd->generation) return;
5075    _it->itc = itc;
5076    _it->item->nocache_once = EINA_TRUE;
5077
5078    elm_widget_stringlist_free(_it->texts);
5079    _it->texts = NULL;
5080    elm_widget_stringlist_free(_it->contents);
5081    _it->contents = NULL;
5082    elm_widget_stringlist_free(_it->states);
5083    _it->states = NULL;
5084
5085    if (_it->flipped)
5086      {
5087         elm_widget_stringlist_free(_it->item->flip_contents);
5088         _it->item->flip_contents = NULL;
5089      }
5090    if (_it->item->deco_it_view)
5091      {
5092         elm_widget_stringlist_free(_it->item->deco_it_texts);
5093         _it->item->deco_it_texts = NULL;
5094         elm_widget_stringlist_free(_it->item->deco_it_contents);
5095         _it->item->deco_it_contents = NULL;
5096      }
5097    if (_it->wd->decorate_all_mode)
5098      {
5099         elm_widget_stringlist_free(_it->item->deco_all_texts);
5100         _it->item->deco_all_texts = NULL;
5101         elm_widget_stringlist_free(_it->item->deco_all_contents);
5102         _it->item->deco_all_contents = NULL;
5103      }
5104
5105    elm_genlist_item_update(it);
5106 }
5107
5108 EAPI const Elm_Genlist_Item_Class *
5109 elm_genlist_item_item_class_get(const Elm_Object_Item *it)
5110 {
5111    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5112    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5113    if (_it->generation < _it->wd->generation) return NULL;
5114    return _it->itc;
5115 }
5116
5117 static Evas_Object *
5118 _elm_genlist_item_label_create(void        *data,
5119                                Evas_Object *obj __UNUSED__,
5120                                Evas_Object *tooltip,
5121                                void        *it __UNUSED__)
5122 {
5123    Evas_Object *label = elm_label_add(tooltip);
5124    if (!label)
5125      return NULL;
5126    elm_object_style_set(label, "tooltip");
5127    elm_object_text_set(label, data);
5128    return label;
5129 }
5130
5131 static void
5132 _elm_genlist_item_label_del_cb(void        *data,
5133                                Evas_Object *obj __UNUSED__,
5134                                void        *event_info __UNUSED__)
5135 {
5136    eina_stringshare_del(data);
5137 }
5138
5139 EAPI void
5140 elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
5141                                   const char      *text)
5142 {
5143    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5144    text = eina_stringshare_add(text);
5145    elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
5146                                            text,
5147                                            _elm_genlist_item_label_del_cb);
5148 }
5149
5150 EAPI void
5151 elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item           *it,
5152                                         Elm_Tooltip_Item_Content_Cb func,
5153                                         const void                 *data,
5154                                         Evas_Smart_Cb               del_cb)
5155 {
5156    ELM_OBJ_ITEM_CHECK_OR_GOTO(it, error);
5157    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5158
5159    if ((_it->tooltip.content_cb == func) && (_it->tooltip.data == data))
5160      return;
5161
5162    if (_it->tooltip.del_cb)
5163      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(it), it);
5164
5165    _it->tooltip.content_cb = func;
5166    _it->tooltip.data = data;
5167    _it->tooltip.del_cb = del_cb;
5168
5169    if (VIEW(_it))
5170      {
5171         elm_widget_item_tooltip_content_cb_set(_it,
5172                                                _it->tooltip.content_cb,
5173                                                _it->tooltip.data, NULL);
5174         elm_widget_item_tooltip_style_set(_it, _it->tooltip.style);
5175         elm_widget_item_tooltip_window_mode_set(_it, _it->tooltip.free_size);
5176      }
5177
5178    return;
5179
5180 error:
5181    if (del_cb) del_cb((void *)data, NULL, NULL);
5182 }
5183
5184 EAPI void
5185 elm_genlist_item_tooltip_unset(Elm_Object_Item *it)
5186 {
5187    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5188    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5189
5190    if ((VIEW(_it)) && (_it->tooltip.content_cb))
5191      elm_widget_item_tooltip_unset(_it);
5192
5193    if (_it->tooltip.del_cb)
5194      _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(_it), _it);
5195    _it->tooltip.del_cb = NULL;
5196    _it->tooltip.content_cb = NULL;
5197    _it->tooltip.data = NULL;
5198    _it->tooltip.free_size = EINA_FALSE;
5199    if (_it->tooltip.style)
5200      elm_genlist_item_tooltip_style_set(it, NULL);
5201 }
5202
5203 EAPI void
5204 elm_genlist_item_tooltip_style_set(Elm_Object_Item  *it,
5205                                    const char       *style)
5206 {
5207    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5208    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5209
5210    eina_stringshare_replace(&_it->tooltip.style, style);
5211    if (VIEW(_it)) elm_widget_item_tooltip_style_set(_it, style);
5212 }
5213
5214 EAPI const char *
5215 elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
5216 {
5217    return elm_object_item_tooltip_style_get(it);
5218 }
5219
5220 EAPI Eina_Bool
5221 elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *it,
5222                                          Eina_Bool disable)
5223 {
5224    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5225    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5226
5227    _it->tooltip.free_size = disable;
5228    if (VIEW(_it)) return elm_widget_item_tooltip_window_mode_set(_it, disable);
5229    return EINA_TRUE;
5230 }
5231
5232 EAPI Eina_Bool
5233 elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *it)
5234 {
5235    return elm_object_tooltip_window_mode_get(VIEW(it));
5236 }
5237
5238 EAPI void
5239 elm_genlist_item_cursor_set(Elm_Object_Item  *it,
5240                             const char       *cursor)
5241 {
5242    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5243    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5244    eina_stringshare_replace(&_it->mouse_cursor, cursor);
5245    if (VIEW(_it)) elm_widget_item_cursor_set(_it, cursor);
5246 }
5247
5248 EAPI const char *
5249 elm_genlist_item_cursor_get(const Elm_Object_Item *it)
5250 {
5251    return elm_widget_item_cursor_get(it);
5252 }
5253
5254 EAPI void
5255 elm_genlist_item_cursor_unset(Elm_Object_Item *it)
5256 {
5257    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5258    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5259
5260    if (!_it->mouse_cursor) return;
5261
5262    if (VIEW(_it)) elm_widget_item_cursor_unset(_it);
5263
5264    eina_stringshare_del(_it->mouse_cursor);
5265    _it->mouse_cursor = NULL;
5266 }
5267
5268 EAPI void
5269 elm_genlist_item_cursor_style_set(Elm_Object_Item  *it,
5270                                   const char       *style)
5271 {
5272    elm_widget_item_cursor_style_set(it, style);
5273 }
5274
5275 EAPI const char *
5276 elm_genlist_item_cursor_style_get(const Elm_Object_Item *it)
5277 {
5278    return elm_widget_item_cursor_style_get(it);
5279 }
5280
5281 EAPI void
5282 elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *it,
5283                                         Eina_Bool        engine_only)
5284 {
5285    elm_widget_item_cursor_engine_only_set(it, engine_only);
5286 }
5287
5288 EAPI Eina_Bool
5289 elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it)
5290 {
5291    return elm_widget_item_cursor_engine_only_get(it);
5292 }
5293
5294 EAPI int
5295 elm_genlist_item_index_get(const Elm_Object_Item *it)
5296 {
5297    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, -1);
5298    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5299
5300    if (_it->item->block)
5301      return _it->position + (_it->item->block->position * _it->wd->max_items_per_block);
5302    return -1;
5303 }
5304
5305 EAPI void
5306 elm_genlist_mode_set(Evas_Object  *obj,
5307                      Elm_List_Mode mode)
5308 {
5309    ELM_CHECK_WIDTYPE(obj, widtype);
5310    Widget_Data *wd = elm_widget_data_get(obj);
5311    if (!wd) return;
5312    if (wd->mode == mode) return;
5313    wd->mode = mode;
5314    if (wd->mode == ELM_LIST_COMPRESS)
5315      elm_genlist_homogeneous_set(obj, EINA_FALSE);
5316    _sizing_eval(obj);
5317 }
5318
5319
5320 EAPI Elm_List_Mode
5321 elm_genlist_mode_get(const Evas_Object *obj)
5322 {
5323    ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
5324    Widget_Data *wd = elm_widget_data_get(obj);
5325    if (!wd) return ELM_LIST_LAST;
5326    return wd->mode;
5327 }
5328
5329 EAPI void
5330 elm_genlist_bounce_set(Evas_Object *obj,
5331                        Eina_Bool    h_bounce,
5332                        Eina_Bool    v_bounce)
5333 {
5334    ELM_CHECK_WIDTYPE(obj, widtype);
5335    Widget_Data *wd = elm_widget_data_get(obj);
5336    if (!wd) return;
5337    wd->h_bounce = !!h_bounce;
5338    wd->v_bounce = !!v_bounce;
5339    elm_smart_scroller_bounce_allow_set(wd->scr, wd->h_bounce, wd->v_bounce);
5340 }
5341
5342 EAPI void
5343 elm_genlist_bounce_get(const Evas_Object *obj,
5344                        Eina_Bool         *h_bounce,
5345                        Eina_Bool         *v_bounce)
5346 {
5347    ELM_CHECK_WIDTYPE(obj, widtype);
5348    Widget_Data *wd = elm_widget_data_get(obj);
5349    if (!wd) return;
5350    if (h_bounce) *h_bounce = wd->h_bounce;
5351    if (v_bounce) *v_bounce = wd->v_bounce;
5352 }
5353
5354 EAPI void
5355 elm_genlist_homogeneous_set(Evas_Object *obj,
5356                             Eina_Bool    homogeneous)
5357 {
5358    ELM_CHECK_WIDTYPE(obj, widtype);
5359    Widget_Data *wd = elm_widget_data_get(obj);
5360    if (!wd) return;
5361    wd->homogeneous = !!homogeneous;
5362 }
5363
5364 EAPI Eina_Bool
5365 elm_genlist_homogeneous_get(const Evas_Object *obj)
5366 {
5367    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5368    Widget_Data *wd = elm_widget_data_get(obj);
5369    if (!wd) return EINA_FALSE;
5370    return wd->homogeneous;
5371 }
5372
5373 EAPI void
5374 elm_genlist_block_count_set(Evas_Object *obj,
5375                             int          count)
5376 {
5377    ELM_CHECK_WIDTYPE(obj, widtype);
5378    Widget_Data *wd = elm_widget_data_get(obj);
5379    if (!wd) return;
5380    wd->max_items_per_block = count;
5381    wd->item_cache_max = wd->max_items_per_block * 2;
5382    _item_cache_clean(wd);
5383 }
5384
5385 EAPI int
5386 elm_genlist_block_count_get(const Evas_Object *obj)
5387 {
5388    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5389    Widget_Data *wd = elm_widget_data_get(obj);
5390    if (!wd) return 0;
5391    return wd->max_items_per_block;
5392 }
5393
5394 EAPI void
5395 elm_genlist_longpress_timeout_set(Evas_Object *obj,
5396                                   double       timeout)
5397 {
5398    ELM_CHECK_WIDTYPE(obj, widtype);
5399    Widget_Data *wd = elm_widget_data_get(obj);
5400    if (!wd) return;
5401    wd->longpress_timeout = timeout;
5402 }
5403
5404 EAPI double
5405 elm_genlist_longpress_timeout_get(const Evas_Object *obj)
5406 {
5407    ELM_CHECK_WIDTYPE(obj, widtype) 0;
5408    Widget_Data *wd = elm_widget_data_get(obj);
5409    if (!wd) return 0;
5410    return wd->longpress_timeout;
5411 }
5412
5413 EAPI void
5414 elm_genlist_scroller_policy_set(Evas_Object        *obj,
5415                                 Elm_Scroller_Policy policy_h,
5416                                 Elm_Scroller_Policy policy_v)
5417 {
5418    ELM_CHECK_WIDTYPE(obj, widtype);
5419    Widget_Data *wd = elm_widget_data_get(obj);
5420    if ((!wd) || (!wd->scr)) return;
5421    if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
5422        (policy_v >= ELM_SCROLLER_POLICY_LAST))
5423      return;
5424    elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
5425 }
5426
5427 EAPI void
5428 elm_genlist_scroller_policy_get(const Evas_Object   *obj,
5429                                 Elm_Scroller_Policy *policy_h,
5430                                 Elm_Scroller_Policy *policy_v)
5431 {
5432    ELM_CHECK_WIDTYPE(obj, widtype);
5433    Widget_Data *wd = elm_widget_data_get(obj);
5434    Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
5435    if ((!wd) || (!wd->scr)) return;
5436    elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
5437    if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
5438    if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
5439 }
5440
5441 EAPI void
5442 elm_genlist_realized_items_update(Evas_Object *obj)
5443 {
5444    ELM_CHECK_WIDTYPE(obj, widtype);
5445
5446    Eina_List *list, *l;
5447    Elm_Object_Item *it;
5448
5449    list = elm_genlist_realized_items_get(obj);
5450    EINA_LIST_FOREACH(list, l, it)
5451      elm_genlist_item_update(it);
5452 }
5453
5454 EAPI void
5455 elm_genlist_item_decorate_mode_set(Elm_Object_Item  *it,
5456                                    const char       *decorate_it_type,
5457                                    Eina_Bool         decorate_it_set)
5458 {
5459    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5460    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5461
5462    Widget_Data *wd = _it->wd;
5463    Eina_List *l;
5464    Elm_Object_Item *it2;
5465
5466    if (!wd) return;
5467    if (!decorate_it_type) return;
5468    if ((_it->generation < _it->wd->generation) ||
5469        elm_widget_item_disabled_get(_it)) return;
5470    if (wd->decorate_all_mode) return;
5471
5472    if ((wd->mode_item == _it) &&
5473        (!strcmp(decorate_it_type, wd->decorate_it_type)) &&
5474        (decorate_it_set))
5475       return;
5476    if (!_it->itc->decorate_item_style) return;
5477    _it->decorate_it_set = decorate_it_set;
5478
5479    if (wd->multi)
5480      {
5481         EINA_LIST_FOREACH(wd->selected, l, it2)
5482           if (((Elm_Gen_Item *)it2)->realized)
5483             elm_genlist_item_selected_set(it2, EINA_FALSE);
5484      }
5485    else
5486      {
5487         it2 = elm_genlist_selected_item_get(wd->obj);
5488         if ((it2) && (((Elm_Gen_Item *)it2)->realized))
5489           elm_genlist_item_selected_set(it2, EINA_FALSE);
5490      }
5491
5492    if (((wd->decorate_it_type) && (strcmp(decorate_it_type, wd->decorate_it_type))) ||
5493        (decorate_it_set) || ((_it == wd->mode_item) && (!decorate_it_set)))
5494      _decorate_item_unset(wd);
5495
5496    eina_stringshare_replace(&wd->decorate_it_type, decorate_it_type);
5497    if (decorate_it_set) _decorate_item_set(_it);
5498 }
5499
5500 EAPI const char *
5501 elm_genlist_item_decorate_mode_get(const Elm_Object_Item *it)
5502 {
5503    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5504    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5505    return _it->wd->decorate_it_type;
5506 }
5507
5508 EAPI const Elm_Object_Item *
5509 elm_genlist_decorated_item_get(const Evas_Object *obj)
5510 {
5511    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5512    Widget_Data *wd = elm_widget_data_get(obj);
5513    if (!wd) return NULL;
5514    return (Elm_Object_Item *) wd->mode_item;
5515 }
5516
5517 EAPI Eina_Bool
5518 elm_genlist_decorate_mode_get(const Evas_Object *obj)
5519 {
5520    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5521    Widget_Data *wd = elm_widget_data_get(obj);
5522    if (!wd) return EINA_FALSE;
5523
5524    return wd->decorate_all_mode;
5525 }
5526
5527 EAPI void
5528 elm_genlist_decorate_mode_set(Evas_Object *obj, Eina_Bool decorated)
5529 {
5530    ELM_CHECK_WIDTYPE(obj, widtype);
5531    Eina_List *list, *l;
5532    Elm_Gen_Item *it;
5533
5534    Widget_Data *wd = elm_widget_data_get(obj);
5535    if (!wd) return;
5536    decorated = !!decorated;
5537    if (wd->decorate_all_mode == decorated) return;
5538    wd->decorate_all_mode = decorated;
5539
5540    list = elm_genlist_realized_items_get(obj);
5541    if (!wd->decorate_all_mode)
5542      {
5543         EINA_LIST_FOREACH(list, l, it)
5544           {
5545              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
5546                _decorate_all_item_unrealize(it);
5547           }
5548         _item_cache_zero(wd);
5549      }
5550    else
5551      {
5552         EINA_LIST_FOREACH(list, l, it)
5553           {
5554              if (it->item->type != ELM_GENLIST_ITEM_GROUP)
5555                {
5556                   if (it->itc->decorate_all_item_style)
5557                      _decorate_all_item_realize(it, EINA_TRUE);
5558                }
5559           }
5560      }
5561    if (wd->calc_job) ecore_job_del(wd->calc_job);
5562    wd->calc_job = ecore_job_add(_calc_job, wd);
5563 }
5564
5565 EAPI void
5566 elm_genlist_reorder_mode_set(Evas_Object *obj,
5567                              Eina_Bool    reorder_mode)
5568 {
5569    ELM_CHECK_WIDTYPE(obj, widtype);
5570    Widget_Data *wd = elm_widget_data_get(obj);
5571    if (!wd) return;
5572    wd->reorder_mode = !!reorder_mode;
5573 }
5574
5575 EAPI Eina_Bool
5576 elm_genlist_reorder_mode_get(const Evas_Object *obj)
5577 {
5578    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5579    Widget_Data *wd = elm_widget_data_get(obj);
5580    if (!wd) return EINA_FALSE;
5581    return wd->reorder_mode;
5582 }
5583
5584 EAPI Elm_Genlist_Item_Type
5585 elm_genlist_item_type_get(const Elm_Object_Item *it)
5586 {
5587    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_GENLIST_ITEM_MAX);
5588    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5589    return _it->item->type;
5590 }
5591
5592 EAPI Elm_Genlist_Item_Class *
5593 elm_genlist_item_class_new(void)
5594 {
5595    Elm_Genlist_Item_Class *itc;
5596
5597    itc = calloc(1, sizeof(Elm_Genlist_Item_Class));
5598    if (!itc)
5599      return NULL;
5600    itc->version = CLASS_ALLOCATED;
5601    itc->refcount = 1;
5602    itc->delete_me = EINA_FALSE;
5603
5604    return itc;
5605 }
5606
5607 EAPI void
5608 elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc)
5609 {
5610    if (itc && (itc->version == CLASS_ALLOCATED))
5611      {
5612         if (!itc->delete_me) itc->delete_me = EINA_TRUE;
5613         if (itc->refcount > 0) elm_genlist_item_class_unref(itc);
5614         else
5615           {
5616              itc->version = 0;
5617              free(itc);
5618           }
5619      }
5620 }
5621
5622 EAPI void
5623 elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc)
5624 {
5625    if (itc && (itc->version == CLASS_ALLOCATED))
5626      {
5627         itc->refcount++;
5628         if (itc->refcount == 0) itc->refcount--;
5629      }
5630 }
5631
5632 EAPI void
5633 elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc)
5634 {
5635    if (itc && (itc->version == CLASS_ALLOCATED))
5636      {
5637         if (itc->refcount > 0) itc->refcount--;
5638         if (itc->delete_me && (!itc->refcount))
5639           elm_genlist_item_class_free(itc);
5640      }
5641 }
5642
5643 void _flip_job(void *data)
5644 {
5645    Elm_Gen_Item *it = (Elm_Gen_Item *) data;
5646    _item_unhighlight(it);
5647    _item_unselect(it);
5648    _elm_genlist_item_unrealize(it, EINA_FALSE);
5649    it->flipped = EINA_TRUE;
5650    it->item->nocache = EINA_TRUE;
5651    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
5652    it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
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      }
5669    else
5670      {
5671         _it->flipped = flip;
5672         _item_cache_zero(_it->wd);
5673         elm_genlist_item_update(it);
5674         _it->item->nocache = EINA_FALSE;
5675      }
5676 }
5677
5678 EAPI Eina_Bool
5679 elm_genlist_item_flip_get(const Elm_Object_Item *it)
5680 {
5681    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5682    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5683    return _it->flipped;
5684 }
5685
5686 EAPI void
5687 elm_genlist_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode)
5688 {
5689    ELM_CHECK_WIDTYPE(obj, widtype);
5690    Widget_Data *wd = elm_widget_data_get(obj);
5691    if (!wd) return;
5692    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
5693      return;
5694    if (wd->select_mode != mode)
5695      wd->select_mode = mode;
5696 }
5697
5698 EAPI Elm_Object_Select_Mode
5699 elm_genlist_select_mode_get(const Evas_Object *obj)
5700 {
5701    ELM_CHECK_WIDTYPE(obj, widtype) ELM_OBJECT_SELECT_MODE_MAX;
5702    Widget_Data *wd = elm_widget_data_get(obj);
5703    if (!wd) return ELM_OBJECT_SELECT_MODE_MAX;
5704    return wd->select_mode;
5705 }
5706
5707 EAPI void
5708 elm_genlist_highlight_mode_set(Evas_Object *obj,
5709                                Eina_Bool    highlight)
5710 {
5711    ELM_CHECK_WIDTYPE(obj, widtype);
5712    Widget_Data *wd = elm_widget_data_get(obj);
5713    if (!wd) return;
5714    wd->highlight = !!highlight;
5715 }
5716
5717 EAPI Eina_Bool
5718 elm_genlist_highlight_mode_get(const Evas_Object *obj)
5719 {
5720    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5721    Widget_Data *wd = elm_widget_data_get(obj);
5722    if (!wd) return EINA_FALSE;
5723    return wd->highlight;
5724 }
5725
5726 EAPI void
5727 elm_genlist_item_select_mode_set(Elm_Object_Item *it,
5728                                  Elm_Object_Select_Mode mode)
5729 {
5730    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5731    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5732    if (!_it) return;
5733    if (_it->generation < _it->wd->generation) return;
5734    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
5735      return;
5736    if (_it->select_mode != mode)
5737      _it->select_mode = mode;
5738
5739    if (_it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
5740      {
5741         _it->item->mincalcd = EINA_FALSE;
5742         _it->item->updateme = EINA_TRUE;
5743         if (_it->item->block) _it->item->block->updateme = EINA_TRUE;
5744         if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
5745         _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
5746      }
5747 }
5748
5749 EAPI Elm_Object_Select_Mode
5750 elm_genlist_item_select_mode_get(const Elm_Object_Item *it)
5751 {
5752    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_OBJECT_SELECT_MODE_MAX);
5753    Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5754    if (!_it) return ELM_OBJECT_SELECT_MODE_MAX;
5755    return _it->select_mode;
5756 }
5757
5758 /* for gengrid as of now */
5759 void
5760 _elm_genlist_page_relative_set(Evas_Object *obj,
5761                                double       h_pagerel,
5762                                double       v_pagerel)
5763 {
5764    Evas_Coord pagesize_h;
5765    Evas_Coord pagesize_v;
5766
5767    ELM_CHECK_WIDTYPE(obj, widtype);
5768    Widget_Data *wd = elm_widget_data_get(obj);
5769    if (!wd) return;
5770
5771    elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
5772    elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
5773                                  pagesize_v);
5774 }
5775
5776 /* for gengrid as of now */
5777 void
5778 _elm_genlist_page_relative_get(const Evas_Object *obj,
5779                                double            *h_pagerel,
5780                                double            *v_pagerel)
5781 {
5782    ELM_CHECK_WIDTYPE(obj, widtype);
5783    Widget_Data *wd = elm_widget_data_get(obj);
5784    if (!wd) return;
5785
5786    elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
5787 }
5788
5789 /* for gengrid as of now */
5790 void
5791 _elm_genlist_page_size_set(Evas_Object *obj,
5792                            Evas_Coord   h_pagesize,
5793                            Evas_Coord   v_pagesize)
5794 {
5795    double pagerel_h;
5796    double pagerel_v;
5797
5798    ELM_CHECK_WIDTYPE(obj, widtype);
5799    Widget_Data *wd = elm_widget_data_get(obj);
5800    if (!wd) return;
5801    elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
5802    elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
5803                                  v_pagesize);
5804 }
5805
5806 /* for gengrid as of now */
5807 void
5808 _elm_genlist_current_page_get(const Evas_Object *obj,
5809                               int               *h_pagenumber,
5810                               int               *v_pagenumber)
5811 {
5812    ELM_CHECK_WIDTYPE(obj, widtype);
5813    Widget_Data *wd = elm_widget_data_get(obj);
5814    if (!wd) return;
5815    elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
5816 }
5817
5818 /* for gengrid as of now */
5819 void
5820 _elm_genlist_last_page_get(const Evas_Object *obj,
5821                            int               *h_pagenumber,
5822                            int               *v_pagenumber)
5823 {
5824    ELM_CHECK_WIDTYPE(obj, widtype);
5825    Widget_Data *wd = elm_widget_data_get(obj);
5826    if (!wd) return;
5827    elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
5828 }
5829
5830 /* for gengrid as of now */
5831 void
5832 _elm_genlist_page_show(const Evas_Object *obj,
5833                        int                h_pagenumber,
5834                        int                v_pagenumber)
5835 {
5836    ELM_CHECK_WIDTYPE(obj, widtype);
5837    Widget_Data *wd = elm_widget_data_get(obj);
5838    if (!wd) return;
5839    elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
5840 }
5841
5842 /* for gengrid as of now */
5843 void
5844 _elm_genlist_page_bring_in(const Evas_Object *obj,
5845                            int                h_pagenumber,
5846                            int                v_pagenumber)
5847 {
5848    ELM_CHECK_WIDTYPE(obj, widtype);
5849    Widget_Data *wd = elm_widget_data_get(obj);
5850    if (!wd) return;
5851    elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
5852 }
5853
5854 void
5855 _elm_genlist_item_unrealize(Elm_Gen_Item *it,
5856                             Eina_Bool     calc)
5857 {
5858    Evas_Object *content;
5859
5860    if (!it->realized) return;
5861    if (it->wd->reorder_it == it) return;
5862
5863    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
5864    if (!calc)
5865      evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
5866    if (it->long_timer)
5867      {
5868         ecore_timer_del(it->long_timer);
5869         it->long_timer = NULL;
5870      }
5871
5872    elm_widget_stringlist_free(it->texts);
5873    it->texts = NULL;
5874    elm_widget_stringlist_free(it->contents);
5875    it->contents = NULL;
5876    elm_widget_stringlist_free(it->states);
5877    it->states = NULL;
5878    EINA_LIST_FREE(it->content_objs, content)
5879      evas_object_del(content);
5880
5881    elm_widget_stringlist_free(it->item->flip_contents);
5882    it->item->flip_contents = NULL;
5883    EINA_LIST_FREE(it->item->flip_content_objs, content)
5884      evas_object_del(content);
5885
5886    it->unrealize_cb(it);
5887
5888    it->realized = EINA_FALSE;
5889    it->want_unrealize = EINA_FALSE;
5890    evas_event_thaw(evas_object_evas_get(WIDGET(it)));
5891    evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
5892 }
5893
5894 void
5895 _elm_genlist_item_del_notserious(Elm_Gen_Item *it)
5896 {
5897    elm_widget_item_pre_notify_del(it);
5898    it->generation = it->wd->generation - 1; /* This means that the item is deleted */
5899
5900    if ((it->relcount > 0) || (it->walking > 0)) return;
5901
5902    if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
5903
5904    if (it->itc->func.del)
5905      it->itc->func.del((void *)it->base.data, WIDGET(it));
5906 }
5907
5908 void
5909 _elm_genlist_item_del_serious(Elm_Gen_Item *it)
5910 {
5911    _elm_genlist_item_del_notserious(it);
5912    it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
5913    if (it->tooltip.del_cb)
5914      it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
5915    it->wd->walking -= it->walking;
5916    if (it->long_timer)
5917      {
5918         ecore_timer_del(it->long_timer);
5919         it->long_timer = NULL;
5920      }
5921    if (it->group)
5922      it->wd->group_items = eina_list_remove(it->wd->group_items, it);
5923
5924    if (it->wd->state)
5925      {
5926         eina_inlist_sorted_state_free(it->wd->state);
5927         it->wd->state = NULL;
5928      }
5929    if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
5930    it->wd->calc_job = ecore_job_add(it->wd->calc_cb, it->wd);
5931    free(it->item);
5932
5933    it->item = NULL;
5934    if (it->wd->last_selected_item == (Elm_Object_Item *)it)
5935      it->wd->last_selected_item = NULL;
5936    it->wd->item_count--;
5937 }
5938
5939 EAPI void
5940 elm_genlist_tree_effect_enabled_set(Evas_Object *obj, Eina_Bool enabled)
5941 {
5942    ELM_CHECK_WIDTYPE(obj, widtype);
5943    Widget_Data *wd = elm_widget_data_get(obj);
5944    if (!wd) return;
5945    wd->tree_effect_enabled = !!enabled;
5946 }
5947
5948 EAPI Eina_Bool
5949 elm_genlist_tree_effect_enabled_get(const Evas_Object *obj)
5950 {
5951    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5952    Widget_Data *wd = elm_widget_data_get(obj);
5953    if (!wd) return EINA_FALSE;
5954    return wd->tree_effect_enabled;
5955 }
5956
5957 static Evas_Object*
5958 _create_tray_alpha_bg(const Evas_Object *obj)
5959 {
5960    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5961    Widget_Data *wd = elm_widget_data_get(obj);
5962    if (!wd) return NULL;
5963
5964    Evas_Object *bg = NULL;
5965    Evas_Coord ox, oy, ow, oh;
5966
5967    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
5968    bg  =  evas_object_rectangle_add(evas_object_evas_get(wd->obj));
5969    evas_object_color_set(bg,0,0,0,0);
5970    evas_object_resize(bg , ow, oh);
5971    evas_object_move(bg , ox, oy);
5972    return bg ;
5973 }
5974
5975 static void
5976 _item_contract_emit(Elm_Gen_Item *it)
5977 {
5978    Elm_Gen_Item *it2;
5979    Eina_List *l;
5980
5981    edje_object_signal_emit(VIEW(it), "elm,state,contract_flip", "");
5982    it->item->tree_effect_finished = EINA_FALSE;
5983
5984    EINA_LIST_FOREACH(it->item->items, l, it2)
5985      if (it2) _item_contract_emit(it2);
5986 }
5987
5988 static int
5989 _item_tree_effect_before(Elm_Gen_Item *it)
5990 {
5991    Elm_Gen_Item *it2;
5992    Eina_List *l;
5993
5994    EINA_LIST_FOREACH(it->item->items, l, it2)
5995      {
5996         if (it2->parent && (it == it2->parent))
5997           {
5998              if (!it2->realized)
5999                it2->item->tree_effect_hideme = EINA_TRUE;
6000              if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6001                edje_object_signal_emit(VIEW(it2), "elm,state,hide", "");
6002              else if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6003                _item_contract_emit(it2);
6004           }
6005      }
6006    return ECORE_CALLBACK_CANCEL;
6007 }
6008
6009 static void
6010 _item_tree_effect(Widget_Data *wd, int y)
6011 {
6012    Elm_Gen_Item *it = NULL, *expanded_next_it;
6013
6014    expanded_next_it = wd->expanded_next_item;
6015
6016    if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6017      {
6018         it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) expanded_next_it);
6019         while (it)
6020           {
6021              if (it->item->expanded_depth <= expanded_next_it->item->expanded_depth) break;
6022              if (it->item->scrl_y && (it->item->scrl_y <= expanded_next_it->item->old_scrl_y + y) &&
6023                  (it->item->expanded_depth > expanded_next_it->item->expanded_depth))
6024                {
6025                   if (!it->item->tree_effect_finished)
6026                     {
6027                        edje_object_signal_emit(VIEW(it), "flip_item", "");
6028                        _item_position(it, VIEW(it), it->item->scrl_x, it->item->scrl_y);
6029                        it->item->tree_effect_finished = EINA_TRUE;
6030                     }
6031                }
6032              it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it);
6033           }
6034      }
6035    else if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6036      {
6037         it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) expanded_next_it);
6038         while (it)
6039           {
6040              if ((it->item->scrl_y > expanded_next_it->item->old_scrl_y + y) &&
6041                  (it->item->expanded_depth > expanded_next_it->item->expanded_depth))
6042                {
6043                   if (!it->item->tree_effect_finished)
6044                     {
6045                        edje_object_signal_emit(VIEW(it), "elm,state,hide", "");
6046                        it->item->tree_effect_finished = EINA_TRUE;
6047                     }
6048                }
6049              else
6050                break;
6051              it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it);
6052           }
6053      }
6054 }
6055
6056 static void
6057 _item_tree_effect_finish(Widget_Data *wd)
6058 {
6059    Elm_Gen_Item *it = NULL;
6060    const Eina_List *l;
6061
6062    if (wd->tree_effect_animator)
6063      {
6064         if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6065           _item_subitems_clear(wd->expanded_item);
6066         EINA_LIST_FOREACH(wd->expanded_item->item->items, l, it)
6067           {
6068              it->item->tree_effect_finished = EINA_TRUE;
6069              it->item->old_scrl_y = it->item->scrl_y;
6070              if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6071                edje_object_signal_emit(VIEW(it), "elm,state,show", "");
6072           }
6073      }
6074    _item_auto_scroll(wd);
6075    evas_object_lower(wd->alpha_bg);
6076    evas_object_hide(wd->alpha_bg);
6077    wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
6078    if (wd->move_items) wd->move_items = eina_list_free(wd->move_items);
6079
6080    evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
6081    evas_object_smart_callback_call(wd->obj, SIG_TREE_EFFECT_FINISHED, NULL);
6082    evas_object_smart_changed(wd->pan_smart);
6083
6084    wd->tree_effect_animator = NULL;
6085 }
6086
6087 static Eina_Bool
6088 _tree_effect_animator_cb(void *data)
6089 {
6090    Widget_Data *wd = data;
6091    if (!wd) return EINA_FALSE;
6092    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
6093    Elm_Gen_Item *it = NULL, *it2, *expanded_next_it;
6094    const Eina_List *l;
6095    double effect_duration = 0.3, t;
6096    int y = 0, dy = 0, dh = 0;
6097    Eina_Bool end = EINA_FALSE, vis = EINA_TRUE;
6098    int in = 0;
6099
6100    t = ((0.0 > (t = ecore_time_get() - wd->start_time)) ? 0.0 : t);
6101    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
6102    evas_output_viewport_get(evas_object_evas_get(wd->pan_smart), &cvx, &cvy, &cvw, &cvh);
6103    if (t > effect_duration) end = EINA_TRUE;
6104
6105    // Below while statement is needed, when the genlist is resized.
6106    it2 = wd->expanded_item;
6107    while (it2 && vis)
6108      {
6109         evas_object_move(VIEW(it2), it2->item->scrl_x, it2->item->scrl_y);
6110         vis = (ELM_RECTS_INTERSECT(it2->item->scrl_x, it2->item->scrl_y, it2->item->w, it2->item->h,
6111                                    cvx, cvy, cvw, cvh));
6112         it2 = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it2);
6113      }
6114
6115    if (wd->expanded_next_item)
6116      {
6117         expanded_next_it = wd->expanded_next_item;
6118
6119         /* move items */
6120         EINA_LIST_FOREACH(wd->move_items, l, it)
6121           {
6122              if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6123                {
6124                   expanded_next_it->item->old_scrl_y = wd->expanded_item->item->old_scrl_y + wd->expanded_item->item->h;
6125                   if (expanded_next_it->item->scrl_y <= expanded_next_it->item->old_scrl_y) //did not calculate next item position
6126                     expanded_next_it->item->scrl_y = cvy + cvh;
6127
6128                   dy = ((expanded_next_it->item->scrl_y >= (cvy + cvh)) ?
6129                          cvy + cvh : expanded_next_it->item->scrl_y) -
6130                          expanded_next_it->item->old_scrl_y;
6131                }
6132              else if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6133                {
6134                   if (expanded_next_it->item->scrl_y >= expanded_next_it->item->old_scrl_y) //did not calculate next item position
6135                      expanded_next_it->item->old_scrl_y = cvy + cvh;
6136
6137                   if (expanded_next_it->item->old_scrl_y > (cvy + cvh))
6138                     {
6139                        dy = (wd->expanded_item->item->scrl_y + wd->expanded_item->item->h) -
6140                        cvy + cvh;
6141                        expanded_next_it->item->old_scrl_y = cvy + cvh;
6142                     }
6143                   else
6144                     {
6145                        dy = (wd->expanded_item->item->scrl_y + wd->expanded_item->item->h) -
6146                              expanded_next_it->item->old_scrl_y;
6147                     }
6148                }
6149
6150              if (t <= effect_duration)
6151                {
6152                   y = ((1 - (1 - (t / effect_duration)) * (1 - (t /effect_duration))) * dy);
6153                }
6154              else
6155                {
6156                   end = EINA_TRUE;
6157                   y = dy;
6158                }
6159
6160              if (!it->realized)
6161                {
6162                   _item_realize(it, in, 0);
6163                }
6164              in++;
6165
6166              if (it != expanded_next_it)
6167                {
6168                   it->item->old_scrl_y = expanded_next_it->item->old_scrl_y + expanded_next_it->item->h + dh;
6169                   dh += it->item->h;
6170                }
6171
6172              if ((it->item->old_scrl_y + y) < (cvy + cvh))
6173                _item_position(it, VIEW(it),it->item->scrl_x, it->item->old_scrl_y + y);
6174           }
6175         /* tree effect */
6176         _item_tree_effect(wd, y);
6177      }
6178    else
6179      {
6180         int expanded_item_num = 0;
6181         int num = 0;
6182
6183         if (wd->expanded_item)
6184           it = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) wd->expanded_item);
6185
6186         it2 = it;
6187         while (it2)
6188           {
6189              expanded_item_num++;
6190              it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
6191           }
6192
6193         while (it)
6194           {
6195              num++;
6196              if (wd->expanded_item->item->expanded_depth >= it->item->expanded_depth) break;
6197              if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6198                {
6199                   if (!it->item->tree_effect_finished)
6200                     {
6201                        if (t >= (((num - 1) * effect_duration) / expanded_item_num))
6202                          {
6203                             edje_object_signal_emit(VIEW(it), "flip_item", "");
6204                             _item_position(it, VIEW(it), it->item->scrl_x, it->item->scrl_y);
6205                             it->item->tree_effect_finished = EINA_TRUE;
6206                          }
6207                     }
6208                }
6209              it = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
6210           }
6211      }
6212
6213    if (end)
6214      {
6215         _item_tree_effect_finish(wd);
6216         return ECORE_CALLBACK_CANCEL;
6217      }
6218    return ECORE_CALLBACK_RENEW;
6219 }